Нужно ли std::string хранить свой символ в непрерывной части памяти?
Я знаю, что в С++ 98 не требуется std::basic_string<>
и std::vector<>
для использования непрерывного хранилища. Это было замечено как надзор за std::vector<>
, как только это было указано, и, если я правильно помню, исправлено с С++ 03.
Кажется, я помню, что прочитал о дискуссиях, требующих, чтобы std::basic_string<>
использовал непрерывное хранилище, когда С++ 11 все еще назывался С++ 0x, но я не стал внимательно следить за этим обсуждением, и я все еще ограничен С++ 03 на работе, поэтому я не уверен, что с ним стало.
Значит, std::basic_string<>
требуется использовать непрерывное хранилище? (Если это так, то какая версия стандарта требовала его сначала?)
В случае, если вы задаетесь вопросом: это важно, если у вас есть код, передающий результат &str[0]
функции, ожидающей непрерывной записи памяти. (Я знаю о str.data()
, но по очевидным причинам старый код не использует его.)
Ответы
Ответ 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).