Разрешено ли string :: c_str () размещать что-либо в куче? - PullRequest
11 голосов
/ 29 сентября 2010

Если мне нужно получить массив char с NUL-завершением из std::string в ситуации, когда мне нужно быть уверенным, что ничего не будет выделено, безопасно ли использовать c_str для этого? Например, если я нахожусь внутри деструктора и хочу скопировать некоторые данные из string в предварительно выделенный буфер фиксированного размера, могу ли я использовать c_str и быть уверенным, что он ничего не выдаст?

Ответы [ 4 ]

7 голосов
/ 29 сентября 2010

Стандарт гласит, что вызов c_str() может сделать недействительными ссылки, указатели и интеграторы, ссылающиеся на элементы string, что означает, что переопределение разрешено (21.3 / 5 "Шаблон класса basic_string").

Возможно, вы захотите просто позвонить string::copy(), чтобы получить свою копию (вам нужно добавить нулевой терминатор самостоятельно, если вам это нужно).

6 голосов
/ 29 сентября 2010

Нет, стандарт не дает такой гарантии.Единственная гарантия в стандарте C ++ состоит в том, что возвращаемое значение указывает на массив char с тем же содержимым, что и std::string, плюс нуль-терминатор.

Таким образом, он будет соответствовать стандартам дляреализация для хранения своего внутреннего представления каким-либо другим способом, кроме C-строки, и выделения C-строки на лету при вызове c_str, хотя я совершенно уверен, что ни одна широко используемая реализация STL на самом деле не делает этого.

Теперь, что касается C ++ 0x, я слышал (хотя сейчас затрудняюсь найти документацию по этому вопросу), что одним из изменений будет требование, чтобы std::string работалв непрерывном хранилище (аналогичное требование уже существует для std::vector).Таким образом, в этом случае вы можете получить доступ к диапазону от &str[0] до &str[0]+str.length()-1, как если бы это была C-строка без нулевого терминатора.

2 голосов
/ 29 сентября 2010

Стандарт об этом молчит:

21.3.6 [lib.strings.ops]

const charT * c_str () const;1 Возвращает: указатель на начальный элемент массива длины size () + 1, чьи первые элементы size () равны соответствующим элементам строки, управляемой * this, и чей последний элемент является нулевым символом, заданным charT ().

2 Требуется: Программа не должна изменять ни одно из значений, хранящихся в массиве.Кроме того, программа не должна обрабатывать возвращаемое значение как допустимое значение указателя после любого последующего вызова неконстантной функции-члена класса basic_string, которая обозначает тот же объект, что и этот.

Может.Тем не менее, я никогда не видел ни одной реализации, которая бы это делала.

Если это вас беспокоит, вы можете рассмотреть возможность использования vector<char> вместо string и делать что-то вроде:

vector<char> chars;
// ...
char* my_str = &chars[0];

Хитрость в том, чтобы понять, когда и как справиться с необходимостью '\0' -определенных строк.

1 голос
/ 29 сентября 2010

Стандарт почти явно говорит о том, что строка может выделять память при вызове c_str.В частности, в нем говорится (§21.3 / 5):

Ссылки, указатели и итераторы, ссылающиеся на элементы последовательности basic_string, могут быть признаны недействительными из-за следующего использования этого объекта basic_string:
[...]
- Вызов функций-членов data () и c_str ().

Он разрешает указателям, ссылкам и итераторам аннулироваться , в частности , чтобы разрешитьреализация для перераспределения памяти, используемой для хранения строки при вызове c_str.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...