Документация верна. Используйте, c_str()
если вам нужна строка с завершающим нулем.
Если разработчики реализовали с data()
точки зрения того, что c_str()
вам не о чем беспокоиться, все равно используйте, data()
если вам не нужно, чтобы строка заканчивалась нулем, в некоторых реализациях это может оказаться лучше, чем c_str ().
строки не обязательно должны состоять из символьных данных, они могут состоять из элементов любого типа. В тех случаях data()
более значимо. c_str()
на мой взгляд, действительно полезно, только когда элементы вашей строки основаны на символах.
Дополнительно : начиная с C ++ 11 обе функции должны быть одинаковыми. т.е. data
теперь требуется, чтобы он завершался нулем. Согласно cppreference : «Возвращаемый массив заканчивается нулем, то есть data () и c_str () выполняют одну и ту же функцию».
.data()
, поэтому они больше не эквивалентны для неконстантных строк.В C ++ 11 / C ++ 0x ,
data()
иc_str()
больше не отличается. И поэтомуdata()
в конце также требуется нулевое завершение.источник
std::string
выделения дополнительного местаchar
для трейлинга'\0'
. Когда вы это сделаетеstd::string s("\0");
, обаs.data()[0]
иs.data()[1]
гарантированноДаже зная, что вы видели, что они делают то же самое или что .data () вызывает .c_str (), неверно предполагать, что это будет иметь место для других компиляторов. Также возможно, что ваш компилятор изменится в будущем выпуске.
2 причины использовать std :: string:
std :: string может использоваться как для текстовых, так и для произвольных двоичных данных.
Вы должны использовать метод .c_str (), когда используете свою строку в качестве примера 1.
Вы должны использовать метод .data (), когда используете свою строку в качестве примера 2. Не потому, что использовать .c_str () в этих случаях опасно, а потому, что это более очевидно, что вы работаете с двоичными данными для других, рассматривающих ваш код.
Возможная ошибка с использованием .data ()
Следующий код неверен и может вызвать segfault в вашей программе:
Почему разработчики часто заставляют .data () и .c_str () делать одно и то же?
Потому что это более эффективно. Единственный способ заставить .data () возвращать что-то, что не завершается нулем, - это скопировать .c_str () или .data () их внутренний буфер или просто использовать 2 буфера. Наличие одного буфера с завершающим нулем всегда означает, что вы всегда можете использовать только один внутренний буфер при реализации std :: string.
источник
На него уже был дан ответ, несколько примечаний о цели: Свобода реализации.
std::string
операции - например, итерация, конкатенация и изменение элементов - не нуждаются в нулевом ограничителе. Если вы не передадите вstring
функцию, ожидающую строку с нулевым завершением, его можно опустить.Это позволило бы реализации иметь подстроки, совместно использующие фактические строковые данные:
string::substr
могло бы внутренне содержать ссылку на общие строковые данные и начальный / конечный диапазон, избегая копирования (и дополнительного выделения) фактических строковых данных. Реализация отложит копирование до тех пор, пока вы не вызовете c_str или не измените какую-либо из строк. Никакая копия не будет сделана, если будут просто прочитаны задействованные строки.(реализация копирования при записи не очень интересна в многопоточных средах, плюс типичная экономия памяти / распределения сегодня не стоит более сложного кода, поэтому это делается редко).
Точно так же
string::data
допускается другое внутреннее представление, например веревка (связанный список сегментов строки). Это может значительно улучшить операции вставки / замены. опять же, список сегментов должен быть свернут до одного сегмента, когда вы вызываетеc_str
илиdata
.источник
Цитата из
ANSI ISO IEC 14882 2003
(Стандарт C ++ 03):источник
Все предыдущие комментарии являются согласованными, но я также хотел бы добавить, что начиная с C ++ 17 str.data () возвращает char * вместо const char *
источник
const
иnon-const
перегрузки доступны с C ++ 17.