Почему постоянная перегрузка std :: string :: data все еще ограничена в современном C ++? - PullRequest
3 голосов
/ 03 июня 2019

std::basic_string::data имеет требование в соответствии с его спецификацией .

[string.accessors] (выделение мое)

const charT* c_str() const noexcept;
const charT* data() const noexcept;

1 Возвращает : указатель p такой, что p + i == &operator[](i) для каждого i в [0, size()].

2 Сложность : постоянное время.

3 Требуется : Программа не должна изменять никакие значения, хранящиеся в массиве символов .

Это имеет смысл в C ++03 для c_str, потому что не нужно возвращать указатель на фактический строковый буфер, и для data, потому что COW была возможной стратегией реализации.Даже если буфер на самом деле не был константным, изменение data мешало бы инвариантам COW.

Но поскольку C ++ 11 COW не разрешен, c_str и data возвращают один и тот же указательи это к самому буферу operator[] позволит модифицировать.Почему же тогда изменение указателя с помощью const_cast<CharT*>(s.data()) все еще явно не определено?Есть ли практическая причина?

1 Ответ

8 голосов
/ 03 июня 2019

Я говорю не о константном std::string, а о неконстантном.

И вот почему это утверждение существует (и продолжает существовать даже вC ++ 17, когда был добавлен не-const data).Потому что data не знает, что .

В реализации string, оптимизированной для небольших строк, сам объект string хранит массив символов.Если этот string объект объявлен const, то и его подобъекты тоже. Модификация объектов, объявленных как const - это UB .

В отличие от этого vector::data не имеет такого утверждения, поскольку const vector всегда выделяет кучу своего массива,Таким образом, хотя массив логически const извне, он технически хорошо определен (но на самом деле действительно не должен) до const_cast возвращаемого значения из const vector::data, поскольку вы изменяете объект, который не был создан как const.

Если бы у basic_string::data не было такого утверждения, реализация на основе единого входа была бы невозможна, потому что это было бы legal для изменения элементов const string, так же, как законно изменять элементы const vector.Но это не может быть законно, чтобы изменить его, потому что это может быть const объект, данные которого хранятся внутри.

...