O std :: string contém terminador nulo?

87

A string abaixo conterá o terminador nulo '\ 0'?

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

Obrigado! :)

senhor
fonte
1
Neste momento, a resposta aceita de @jahhaj conflita com a resposta do usuário 529758, cuja resposta é indiscutivelmente mais atualizada. Enquanto examinava com atenção, pulei o comentário de Jesse Good, então, aqui está para enfatizar sua importância.
Jonathan Komar

Respostas:

99

Não, mas se você disser, temp.c_str()um terminador nulo será incluído no retorno desse método.

Também vale a pena dizer que você pode incluir um caractere nulo em uma string como qualquer outro caractere.

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

estampas

5 5

e não 5 1como você poderia esperar se os caracteres nulos tivessem um significado especial para strings.

jahhaj
fonte
5
Se você chamar, temp.c_str()o caractere nulo será incluído. Se você realmente precisar dele na string, basta adicioná-lo como qualquer outro caractere. temp.push_back('\0'). Agora temp.c_str()incluirá dois caracteres nulos.
jahhaj 01 de
1
@dupdupdup, como algumas das respostas mencionaram, se você precisa de uma string terminada em nulo, você deve chamar um s.c_str () no objeto construído. Ele retornará um ponteiro para a matriz de caracteres que tem a garantia de '\ 0' no final.
Maksim Skurydzin 01 de
@Rico, Jahhaj Como terminar a string então. Por exemplo - adicionei alguns caracteres à minha string como str [i]. Agora não consigo imprimir usando cout.
Bhavuk Mathur
Para adicionar ao seu ponto: Uma vez que o operador << está sobrecarregado, cout << s, irá embora imprimir a string completa caractere por caractere, mas, se você pegar c_str () e colocar no operador <<, ele imprimirá até o null char. o programa a seguir ilustra esse ponto. {string s ("SampleString"); cout << s.size () << "\ t" << s << endl; s [3] = '\ 0'; cout << "\ n \ n Depois de nulo \ n \ n" << s.size () << "\ t" << s << endl; cout << "\ n \ n Obtendo c_str \ n \ n" << s.size () << "\ t" << s.c_str () << endl; }
Fooo
70

Não em C ++ 03, e nem mesmo é garantido antes de C ++ 11 que em uma C ++ std :: string seja contínua na memória. Apenas strings C (matrizes de caracteres destinadas ao armazenamento de strings) tinham o terminador nulo.

No C ++ 11 e posterior, mystring.c_str()é equivalente a mystring.data()é equivalente a &mystring[0]e mystring[mystring.size()]é garantido que seja '\0'.

Quuxplusone
fonte
4
Com o C ++ 11, as strings agora têm a garantia de serem contíguas na memória.
zneak 01 de
@zneak obrigado! Atualizada. Mas eu duvido que haja pelo menos algum compilador C ++ 11-compilador razoavelmente ... até mesmo GCC quebrou o suporte para ele.
4
@ H2CO3: C ++ 11 à parte, isso foi abordado no DR 530 em 2005 . A grande maioria das implementações de bibliotecas padrão armazenam dados de string em memória contígua por pelo menos o mesmo tempo.
ildjarn 01 de
3
Obrigado @ildjarn, eu estava procurando exatamente isso. Parte da justificativa para a mudança foi que ninguém no comitê sabia de uma implementação de STL que não usasse memória contínua.
zneak 01 de
7
@ H2CO3: Honestamente, se isso te ofendeu, você precisa de uma pele mais grossa.
ildjarn
8

Isso depende da sua definição de 'conter' aqui. No

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

há algumas coisas a serem observadas:

  • temp.size()retornará o número de caracteres do primeiro hao último p(ambos inclusivos)
  • Mas ao mesmo tempo temp.c_str()ou temp.data()vai voltar com um nullterminador
  • Ou em outras palavras int(temp[temp.size()])será zero

Eu sei, pareço com algumas das respostas aqui, mas quero salientar que sizede std::stringem C++é mantido separadamente e não é como em Conde você continua contando a menos que encontre o primeiro nullterminador.

Para adicionar, a história seria um pouco diferente se você string literalcontivesse incorporado \0. Nesse caso, a construção das std::stringparadas no primeiro nullcaractere, conforme segue:

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

Referências:

aniliitb10
fonte
2

Sim, se você chamar temp.c_str(), ele retornará uma string C terminada em nulo.

No entanto, os dados reais armazenados no objeto tempnão podem ter terminação nula, mas não importa e não deve importar para o programador, porque quando o programador quiser const char*, ele chamaria c_str()o objeto, que é garantido para retornar nulo string terminada.

Nawaz
fonte
1
Nem o terminador nulo (se existir) será incluído no retorno de temp.size().
jahhaj de
1

Com strings C ++ você não precisa se preocupar com isso, e possivelmente depende da implementação.

Usando temp.c_str()você obtém uma representação C da string, que definitivamente conterá o \0char. Além disso, não vejo como seria útil em uma string C ++

Naps62
fonte
1

std::stringmantém internamente uma contagem do número de caracteres. Internamente funciona usando esta contagem. Como outros disseram, quando você precisa da string para exibição ou qualquer outro motivo, você pode c_str()usar seu método que fornecerá a string com o terminador nulo no final.

Super homen
fonte
Você pode dar algumas referências para esta declaração, "std :: string internamente mantém uma contagem do número de caracteres. Internamente funciona usando essa contagem"
rimalonfire