Содержит ли std :: string нулевой терминатор?

87

Будет ли строка ниже содержать нулевой терминатор '\ 0'?

std::string temp = "hello whats up";

Благодарность! :)

Мистер
источник
1
В настоящее время принятый ответ от @jahhaj конфликтует с ответом пользователя529758, чей ответ, возможно, более актуален. При просмотре я пропустил комментарий Джесси Гуда, поэтому здесь, чтобы подчеркнуть его важность.
Джонатан Комар,

Ответы:

99

Нет, но если вы скажете temp.c_str(), что в возврат из этого метода будет включен нулевой терминатор.

Также стоит сказать, что вы можете включать в строку нулевой символ, как и любой другой символ.

string s("hello");
cout << s.size() << ' ';
s[1] = '\0';
cout << s.size() << '\n';

печатает

5 5

и не так, 5 1как вы могли бы ожидать, если бы нулевые символы имели особое значение для строк.

джахадж
источник
5
При вызове temp.c_str()будет включен нулевой символ. Если он вам действительно нужен в строке, просто добавьте его, как любой другой символ. temp.push_back('\0'). Теперь temp.c_str()будет включать два нулевых символа.
jahhaj 01
1
@dupdupdup, как упоминалось в некоторых ответах, если вам нужна строка с завершающим нулем, вы должны вызвать s.c_str () для созданного объекта. Он вернет указатель на массив символов, который гарантированно будет иметь '\ 0' в конце.
Максим Скуридзин 01
@Rico, Jahhaj Как тогда закончить строку. Например, я добавил несколько символов в свою строку как str [i]. Теперь я не могу распечатать его с помощью cout.
Бхавук Матур
Чтобы добавить к вашей точке: Поскольку оператор << перегружен, поэтому cout << s, хотя будет печатать полную строку char с помощью char, но, если вы возьмете c_str () и поместите в operator <<, он будет печатать до нулевой символ. следующая программа отражает этот момент. {строка s ("SampleString"); cout << s.size () << "\ t" << s << endl; s [3] = '\ 0'; cout << "\ n \ n После Null \ n \ n" << s.size () << "\ t" << s << endl; cout << "\ n \ n Принимая c_str \ n \ n" << s.size () << "\ t" << s.c_str () << endl; }
Fooo 02
70

Не в C ++ 03, и до C ++ 11 даже не гарантировалось, что в C ++ std :: string является непрерывным в памяти. Только строки C (массивы символов, предназначенные для хранения строк) имели нулевой терминатор.

В C ++ 11 и более поздних версиях mystring.c_str()эквивалентно mystring.data()эквивалентно &mystring[0]и mystring[mystring.size()]гарантированно будет '\0'.

Quuxplusone
источник
4
В C ++ 11 теперь гарантируется непрерывность строк в памяти.
zneak 01
@zneak спасибо! Обновлено. Но я сомневаюсь, что существуют хоть сколько-нибудь разумно компилирующие компиляторы C ++ 11 ... даже GCC не поддерживает его.
4
@ H2CO3: Помимо C ++ 11, в 2005 году этот вопрос был рассмотрен в DR 530 . Подавляющее большинство реализаций стандартных библиотек хранят строковые данные в непрерывной памяти по крайней мере столько же времени.
ildjarn 01
3
Спасибо @ildjarn, я именно это и искал. Частично этот шаг объяснялся тем, что никто из членов комитета не знал о реализации STL, в которой не использовалась бы непрерывная память.
zneak 01
7
@ H2CO3: Честно говоря, если это вас обидело, вам нужна более толстая кожа.
ildjarn 01
8

Это зависит от вашего определения слова «содержать» здесь. В

std::string temp = "hello whats up";

следует отметить несколько моментов:

  • temp.size()вернет количество символов от первого hдо последнего p(оба включительно)
  • Но заодно temp.c_str()или temp.data()вернется с nullтерминатором
  • Или другими словами int(temp[temp.size()])будет ноль

Я знаю, я звук , похожий на некоторые из ответов здесь , но я хочу отметить, что sizeиз std::stringв C++это поддерживается отдельно , и это не так, как в , Cгде вы храните подсчет , если вы не найдете первый nullтерминатор.

Чтобы добавить, история была бы немного другой, если бы у вас был string literalвстроенный файл \0. В этом случае построение std::stringостанавливается на первом nullсимволе, а именно:

std::string s1 = "ab\0\0cd";   // s1 contains "ab",       using string literal
std::string s2{"ab\0\0cd", 6}; // s2 contains "ab\0\0cd", using different ctr
std::string s3 = "ab\0\0cd"s;  // s3 contains "ab\0\0cd", using ""s operator

Ссылки:

aniliitb10
источник
2

Да, если вы позвоните temp.c_str(), он вернет c-строку с завершающим нулем.

Однако фактические данные, хранящиеся в объекте, tempне могут быть завершены нулем, но это не имеет значения и не должно иметь значения для программиста, потому что, когда программист захочет const char*, он вызовет c_str()объект, который гарантированно вернет null. -завершенная строка.

Наваз
источник
1
Нулевой терминатор (если он существует) также не будет включен в возврат от temp.size().
jahhaj 01
1

Со строками C ++ вам не о чем беспокоиться, и это, возможно, зависит от реализации.

Используя temp.c_str()C, вы получаете представление строки, которое обязательно будет содержать \0символ. Кроме этого, я действительно не понимаю, как это было бы полезно для строки C ++

Дремота62
источник
1

std::stringвнутренне ведет подсчет количества символов. Внутренне это работает с использованием этого подсчета. Как говорили другие, когда вам нужна строка для отображения или по какой-либо причине, вы можете использовать ее c_str()метод, который даст вам строку с нулевым терминатором в конце.

Супермен
источник
Можете ли вы дать несколько ссылок на этот оператор: «std :: string внутренне ведет счет количества символов. Внутренне он работает с использованием этого счетчика»
rimalonfire