Подтвердить что ты не робот

Нужно ли std::string хранить свой символ в непрерывной части памяти?

Я знаю, что в С++ 98 не требуется std::basic_string<> и std::vector<> для использования непрерывного хранилища. Это было замечено как надзор за std::vector<>, как только это было указано, и, если я правильно помню, исправлено с С++ 03.

Кажется, я помню, что прочитал о дискуссиях, требующих, чтобы std::basic_string<> использовал непрерывное хранилище, когда С++ 11 все еще назывался С++ 0x, но я не стал внимательно следить за этим обсуждением, и я все еще ограничен С++ 03 на работе, поэтому я не уверен, что с ним стало.

Значит, std::basic_string<> требуется использовать непрерывное хранилище? (Если это так, то какая версия стандарта требовала его сначала?)

В случае, если вы задаетесь вопросом: это важно, если у вас есть код, передающий результат &str[0] функции, ожидающей непрерывной записи памяти. (Я знаю о str.data(), но по очевидным причинам старый код не использует его.)

4b9b3361

Ответ 1

С++ 11, basic_string 21.4.1.5,

Объекты char -like в объекте basic_string сохраняются смежно. То есть для любого объекта basic_string s идентификатор & * (s.begin() + n) == & * s.begin() + n выполняется для всех значений n такой, что 0 <= n < s.size().

Ответ 2

В С++ 03 не было гарантии, что элементы строки будут храниться непрерывно. [basic.string] был

  • Для типа char -like charT шаблон шаблона basic_string описывает объекты, которые могут хранить последовательность, состоящая из различного числа произвольных char -подобных объектов (статья 21). Первый элемент последовательность находится в нулевом положении. Такая последовательность также называется "строкой", если данный тип charиз контекста. В остальной части этого предложения charT обозначает такой заданный тип char. Хранение для строки выделяется и освобождается по мере необходимости функциями-членами класса basic_string через Класс Allocator передан как параметр шаблона. Allocator:: value_type должен быть таким же, как ДИАГРАММА.
  • Шаблон класса basic_string соответствует требованиям последовательности, как указано в (23.1.1). Кроме того, поскольку итераторы, поддерживаемые basic_string, являются итераторами произвольного доступа (24.1.5), basic_string соответствует требованиям Реверсивного контейнера, как указано в (23.1). 389 ISO/IEC 14882: 2003 (E)  ISO/IEC 21.3 Шаблон класса basic_string 21 Библиотека строк
  • Во всех случаях size() <= capacity().

И затем в С++ 17 они тоже изменили его

  • Шаблон класса basic_string описывает объекты, которые могут хранить последовательность, состоящую из разного числа произвольных char -подобных объектов с первым элементом последовательности в нулевом положении. Такая последовательность также называемой "строкой", если тип объектов char, которые он удерживает, ясен из контекста. В остальной части этого Параметр, тип объектов char, хранящихся в объекте basic_string, обозначается символом charT.
  • Функции-члены basic_string используют объект класса Allocator, переданный как параметр шаблона для размещения и свободного хранения для содержащихся char -подобных объектов .233
  • Базовая_строка - это непрерывный контейнер (23.2.1).
  • Во всех случаях size() <= capacity().

акцент мой

Итак, pre С++ 17 не был гарантирован, но теперь он есть.

С ограничениями, которые std::string::data налагает, эта не гарантия почти спорна, так как вызов std::string::data дает вам непрерывный массив символов в строке. Поэтому, если реализация не делает это по требованию и в течение постоянного времени строка будет непрерывной.


В случае, если вы задаетесь вопросом: это важно, если у вас есть код, передающий результат &str[0] функции, ожидающей записи непрерывной части памяти. (Я знаю о str.data(), но по очевидным причинам старый код не использует его.)

Поведение operator[] также изменилось. В С++ 03 мы имели

Возвращает: Если pos < size(), возвращает данные() [pos]. В противном случае, если pos == size(), const версия возвращает charT(). В противном случае поведение undefined.

Таким образом, гарантируется, что только версия const определила поведение, если вы попытались &s[0], когда s пуст. В С++ 11 они изменили его на:

Возвращает: * (begin() + pos), если pos < размер(). В противном случае возвращает ссылку на объект типа charT со значением charT(), где изменение объекта приводит к поведению undefined.

Итак, теперь обе версии const и non const определили поведение, если вы пробовали &s[0], когда s пуст.

Ответ 3

В соответствии с проектом стандарта N4527 21.4/3 Шаблон класса basic_string [basic.string]:

Базовая_строка является непрерывным контейнером (23.2.1).