Что возвращает метод c_str() из строкового класса?
Я хочу получить начальный адрес массива, который поддерживается классом строк.
string str="hey";
char* pointer=(char*)str.c_str();
-
Указывает ли указатель на адрес массива (поддерживается строковым классом)? или класс string создаст новый массив из динамической памяти и скопирует в него существующую строку и вернет ее адрес?
-
Если это не так, то как получить доступ к начальному адресу массива, который поддерживается классом строк?
Ответы
Ответ 1
В стандарте С++ 11 явно указано, что .c_str()
(а также новый .data()
) должен возвращать указатель на внутренний буфер, который используется std::string
.
Любая модификация std::string после получения указателя через .c_str()
может привести к тому, что упомянутый char *
возвращенный стал недействительным (то есть, если std::string
внутренне пришлось перераспределять пробел).
В предыдущих версиях С++ реализация может вернуть что-либо. Но как стандарт не требует от пользователя освобождения от результата, я никогда не видел, чтобы какая-либо реализация возвращала что-то новое. По меньшей мере GNU gcc и MSVС++ STL-строка являются внутренними нулевыми массивами char, которые возвращаются c_str()
.
Так что безопасно предполагать (с нормальным для С++ предостережения), что в любой версии С++ в любой его реализации .c_str()
будет возвращен внутренний буфер.
Другими словами, вы никогда не должны сохранять значение .c_str()
, если не будете на 100% уверены, что он не изменит его размер в любое время в будущем (если это не const
, то есть).
P.S. BTW, вы никогда не должны делать char* pointer=(char*)str.c_str();
. Это const char *
, и вы не должны изменять содержимое, отчасти потому, что выше - вы можете завершить переписывание памяти какого-либо другого объекта или развратить внутреннее состояние std::string
, если реализация делает что-то фантастическое, например индексирование символов для более быстрого .find()
(новее видели это, но эй - это инкапсуляция!)
Ответ 2
ПРИМЕЧАНИЕ. Мой ответ верен только для pre-С++ 11. Для С++ 11, это является правильным ответом.
-
Он возвращает C-строку с нулевым завершением. std::string
сам по себе не заканчивается на нуль, поэтому реализация разрешена (и, вероятно, будет) возвращать вновь выделенный массив const char
. Если создание std::string
выходит за пределы области видимости или, если оно мутировано, строка c_str()
-вернутая строка недействительна.
-
data()
возвращает данные, но будьте осторожны, это не строка с нулевым завершением.
В любом случае вы должны настроить эти данные, как data()
, так и c_str()
указатели возврата на const char
, и вы действительно не должны этого делать.
Например, std::string
разрешены ссылки на подсчитанные строки (хотя это уже не является обычным явлением) или даже могут использовать фанковые схемы индексирования по их данным (но никогда не видели этого).
Ответ 3
Вы можете получить адрес начала строки char *address = &str[0];
. Нет необходимости преобразовывать строку в представление c-строки.
Ответ 4
Если вы действительно хотите "данные" внутри строки, то string::data()
- это функция, которую вы ищете.
Обратите внимание, что, подобно c_str()
, это указатель const
для данных - вы не должны изменять эти данные.
Ответ 5
В С++ 11 возвращаемый указатель указывает на внутренний массив, используемый в настоящее время строковым объектом для хранения символов, соответствующих его значению.
Подробнее см. http://www.cplusplus.com/reference/string/string/c_str/.