Строка c_str () против данных () - PullRequest
89 голосов
/ 12 октября 2008

Я прочитал несколько мест, что разница между c_str() и data() (в STL и других реализациях) заключается в том, что c_str() всегда завершается нулем, а data() - нет. Насколько я видел в реальных реализациях, они либо делают то же самое, либо data() вызывает c_str().

Что мне здесь не хватает? Какой из них более правильно использовать в каких сценариях?

Ответы [ 6 ]

97 голосов
/ 12 октября 2008

Документация верна. Используйте c_str(), если вы хотите завершить нулем строку.

Если разработчики осуществили data() в терминах c_str(), вам не о чем беспокоиться, все равно используйте data(), если вам не нужна строка, заканчивающаяся нулем, в некоторых реализациях может оказаться лучше, чем c_str ().

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

Extra : В C ++ 11 и далее обе функции должны быть одинаковыми. т. е. data теперь должен заканчиваться нулем. Согласно cppreference : «Возвращенный массив завершается нулем, то есть data () и c_str () выполняют одну и ту же функцию.»

25 голосов
/ 13 сентября 2012

In C ++ 11 / C ++ 0x , data() и c_str() больше не отличаются. И поэтому data() также должен иметь нулевое завершение в конце.

21.4.7.1 basic_string accessors [string.accessors]

const charT* c_str() const noexcept;

const charT* data() const noexcept;

1 Возвращает: указатель p такой, что p + i == &operator[](i) для каждого i в [0,size()].


21.4.5 Доступ к элементу basic_string [string.access]

const_reference operator[](size_type pos) const noexcept;

1 Требуется: pos <= size (). 2 Возвращает: <code>*(begin() + pos) if pos < size(), иначе ссылка на объект типа T со значением charT(); указанное значение не должно изменяться.

18 голосов
/ 12 октября 2008

Даже если вы знаете, что вы видели, что они делают то же самое, или что .data () вызывает .c_str (), неверно полагать, что это будет иметь место для других компиляторов. Также возможно, что ваш компилятор изменится в будущем выпуске.

2 причины использовать std :: string:

std :: string может использоваться как для текстовых, так и для произвольных двоичных данных.

//Example 1
//Plain text:
std::string s1;
s1 = "abc";

//Example 2
//Arbitrary binary data:
std::string s2;
s2.append("a\0b\0b\0", 6);

Вам следует использовать метод .c_str (), когда вы используете вашу строку в качестве примера 1.

Вам следует использовать метод .data (), когда вы используете строку в качестве примера 2. Не потому, что в этих случаях опасно использовать .c_str (), а потому, что вы работаете с двоичными данными более явно для других, просматривающих ваш код.

Возможные ошибки при использовании .data ()

Следующий код неверен и может вызвать ошибку в вашей программе:

std::string s;
s = "abc";   
char sz[512]; 
strcpy(sz, s.data());//This could crash depending on the implementation of .data()

Почему разработчики часто делают .data () и .c_str () одинаковыми?

Потому что это эффективнее. Единственный способ заставить .data () возвращать то, что не завершено нулем, это сделать так, чтобы .c_str () или .data () копировали свой внутренний буфер или просто использовали 2 буфера. Наличие одного буфера с нулевым символом в конце всегда означает, что вы всегда можете использовать только один внутренний буфер при реализации std :: string.

3 голосов
/ 01 июля 2012

Уже было дано несколько замечаний о цели: Свобода реализации.

std::string операции - например, итерация, конкатенация и мутация элемента - не нужен нулевой терминатор. Если вы не передадите string функции, ожидающей строку с нулем в конце, она может быть опущена.

Это позволило бы реализации иметь подстроки совместно использовать фактические строковые данные: string::substr может внутренне содержать ссылку на совместно используемые строковые данные и диапазон начала / конца, избегая копирования (и дополнительного выделения) фактических строковых данных , Реализация будет откладывать копирование до тех пор, пока вы не вызовете c_str или не измените любую из строк. Копия никогда не будет сделана, если только стрингсы будут прочитаны.

(реализация копирования при записи не многим интересна в многопоточных средах, плюс обычная экономия памяти / выделения не стоит сегодня более сложного кода, поэтому это делается редко).


Аналогично, string::data допускает другое внутреннее представление, например, веревка (связанный список сегментов строки). Это может значительно улучшить операции вставки / замены. опять же, список сегментов должен быть свернут в один сегмент при вызове c_str или data.

2 голосов
/ 25 февраля 2019

Все предыдущие комментарии являются консистенцией, но я также хотел бы добавить, что начиная с c ++ 17, str.data () возвращает символ * вместо const char *

1 голос
/ 05 октября 2011

Цитата из ANSI ISO IEC 14882 2003 (стандарт C ++ 03):

    21.3.6 basic_string string operations [lib.string.ops]

    const charT* c_str() const;

    Returns: A pointer to the initial element of an array of length size() + 1 whose first size() elements
equal the corresponding elements of the string controlled by *this and whose last element is a
null character specified by charT().
    Requires: The program shall not alter any of the values stored in the array. Nor shall the program treat the
returned value as a valid pointer value after any subsequent call to a non-const member function of the
class basic_string that designates the same object as this.

    const charT* data() const;

    Returns: If size() is nonzero, the member returns a pointer to the initial element of an array whose first
size() elements equal the corresponding elements of the string controlled by *this. If size() is
zero, the member returns a non-null pointer that is copyable and can have zero added to it.
    Requires: The program shall not alter any of the values stored in the character array. Nor shall the program
treat the returned value as a valid pointer value after any subsequent call to a non- const member
function of basic_string that designates the same object as this.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...