Почему std :: vector :: data и std :: string :: data различаются? - PullRequest
32 голосов
/ 22 сентября 2011

Новый метод Vector data() предоставляет постоянную и неконстантную версию.
Однако метод строки data() предоставляет только постоянную версию.

Я думаю, что они изменили формулировку о std::string, так что теперь символы должны быть смежными (например, std::vector).

Был ли std::string::data пропущен? Или это хорошая причина разрешить постоянный доступ только к символам строки?

примечание: std::vector::data имеет еще одну приятную особенность, это не неопределенное поведение для вызова data() для пустого вектора. Принимая во внимание, что &vec.front() - неопределенное поведение, если оно пустое.

Ответы [ 4 ]

29 голосов
/ 22 сентября 2011

В C ++ 98/03 была веская причина не иметь неконстантного data() из-за того, что строка часто была реализована как COW.Неконстантный data() потребовал бы, чтобы копия была сделана, если счет был больше 1. Хотя это возможно, это не было сочтено желательным в C ++ 98 / 03.

В октябре 2005 г.Комитет проголосовал за LWG 464 , который добавил const и non-const data() к vector и добавил const и non-const at() к map.В то время, string не был изменен, чтобы объявить вне закона COW.Но позже, в C ++ 11, COW string больше не соответствует.Спецификация string также была ужесточена в C ++ 11, так что она должна быть смежной, и всегда есть завершающий нуль, предоставляемый operator[](size()).В C ++ 03 завершающий ноль гарантировался только перегрузкой const operator[].

Таким образом, короче говоря, неконстантный data() выглядит намного более разумным для C ++ 11 string.Насколько я знаю, это никогда не предлагалось.

Обновление

charT* data() noexcept;

было добавлено basic_string в рабочем проекте C ++ 1zN4582 от Дэвида Санкеля P0272R1 на собрании в Джексонвилле в феврале 2016 года.

Отличная работа, Дэвид!

2 голосов
/ 22 сентября 2011

Исторически строковые данные не были постоянными, потому что это предотвратило бы несколько общих оптимизаций, таких как копирование при записи (COW). Это сейчас, IIANM, гораздо реже, потому что он плохо работает с многопоточными программами.

Кстати, да, теперь они должны быть смежными:

[string.require] .5: Символоподобные объекты в объекте basic_string должны храниться непрерывно. То есть для любой basic_string объект s, тождество & * (s.begin () + n) == & * s.begin () + n должно храниться для всех значений n, таких что 0 <= n <s.size (). </p>

Другая причина может заключаться в том, чтобы избегать кода, такого как:

std::string ret;
strcpy(ret.data(), "whatthe...");

Или любая другая функция, которая возвращает предварительно выделенный массив символов.

1 голос
/ 22 сентября 2011

Хотя я не очень хорошо разбираюсь в стандарте, это может быть связано с тем, что std::string не должен содержать данные с нулевым символом в конце, но он может и не должен содержатьполе явной длины, но может.Таким образом, изменение недостоверных данных и, например, добавление '\0' в середине может привести к тому, что поле длины строки не будет синхронизировано с фактическими данными char и, таким образом, оставить объект в недопустимом состоянии.

0 голосов
/ 02 октября 2011

@ Кристиан Рау

С того момента, как комитет по изучению STL-ize (превратившийся в последовательность, шаблонизированный) стал классом Plauger (думаю, примерно в 1995 году), std::string всегда былstd::vector плюс строки, связанные со строкой (преобразование из / в 0, конкатенация, ...), а также некоторые странности, такие как COW, который на самом деле " Копировать при записи и не-const begin() /end() / operator[] ".

Но, в конечном счете, std::string - это действительно std::vector под другим именем, с немного другим фокусом и намерением.Итак:

  • так же, как std::vector, std::string имеет либо элемент данных размера, либо оба элемента с начальным и конечным данными;
  • точно так же, как std::vector, std::stringне заботится о значении его элементов, встроенных NUL или других.

std::string - это не строка C с синтаксическим сахаром, служебными функциями и некоторой инкапсуляцией, как std::vector<T> не T[] с синтаксическим сахаром, служебными функциями и некоторой инкапсуляцией.

...