Почему нельзя изменять строку через извлеченный указатель на ее данные?
В C ++ 11 символыstd::string
должны храниться смежно, как § 21.4.1 / 5 баллов:
Символоподобные объекты в объекте basic_string должны храниться непрерывно. То есть для любого объекта s basic_string идентификатор &* (s.begin () + n) == &* s.begin () + n должно выполняться для всех значений n, таких что 0 <= n < s.size ().
Однако вот как 21.4.7.1 перечисляет две функции для извлечения указателя на основное хранилище (выделено мной):
const charT * c_str () const noexcept;
const charT * data () const noexcept;
1 Возвращает: указатель p такой, что p + i == &оператор [] (i) для каждого i в [0, size ()].
2 Сложность: постоянное время.
3 Требуется: программа не должна изменять никакие значения, хранящиеся в массиве символов.
Одна из возможностей, которую я могу придумать для точки номер 3, заключается в том, что указатель может стать недействительным в результате следующих применений объекта (§ 21.4.1 / 6):
в качестве аргумента любой стандартной библиотечной функции, принимая в качестве аргумента ссылку на неконстантную basic_string.Вызов неконстантных функций-членов, кроме operator [], at, front, back, begin, rbegin, end и rend.Несмотря на это, итераторы могут стать недействительными, но мы все равно можем изменять их, пока они не сделают это. Мы по-прежнему можем использовать указатель, пока он не станет недействительным и для чтения из буфера.
Почему можномы пишем напрямую в этот буфер? Потому что это привело бы класс в противоречивое состояние, как, например,end()
не будет обновляться с новым концом? Если так, то почему разрешено писать прямо в буфер чего-то подобного?std::vector
Варианты использования для этого включают возможность передать буферstd::string
в интерфейс C, чтобы получить строку вместо передачи вvector
вместо этого и инициализируя строку с итераторами из этого:
std::string text;
text.resize(GetTextLength());
GetText(text.data());