Почему нельзя изменять строку через извлеченный указатель на ее данные?

В 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 == & operator [] (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<char> вместо этого и инициализируя строку с итераторами из этого:

std::string text;
text.resize(GetTextLength());
GetText(text.data());

Ответы на вопрос(1)

Ваш ответ на вопрос