当使用字符串文字初始化时,std :: strings是否以'\ 0'结尾?

nek*_*k28 5 c++ string null-terminated subscript-operator

我知道字符串对象不是空终止但为什么这应该工作?

std::string S("Hey");
for(int i = 0; S[i] != '\0'; ++i)
   std::cout << S[i];
Run Code Online (Sandbox Code Playgroud)

所以构造函数也复制了null终止符,但是不增加长度?为什么这么麻烦?

son*_*yao 7

所以构造函数也复制了null终止符,但是不增加长度?

正如您所知,std::string它不包含空字符(并且它不会复制空字符).

关键是你正在使用std::basic_string::operator[].根据C++ 11,当指定的索引等效时,std :: basic_string :: operator []将返回一个空字符size().

如果pos == size(),CharT()则返回对具有值的字符(空字符)的引用.

对于第一个(非const)版本,如果将此字符修改为除以外的任何值,则行为未定义charT().


Kar*_*oll 5

std::string 在内部以以N结尾的C字符串形式存储数据,但是在正常使用中不允许您访问N端。

例如,如果我分配值“ Hello,World!” 到一个字符串,内部缓冲区将如下所示:

std::string myString("Hello, World!");

// Internal Buffer...
// [ H | e | l | l | o | , |   | W | o | r | d | ! | \0 ]
//                                                   ^ Null terminator.
Run Code Online (Sandbox Code Playgroud)

在此示例中,空终止符不是从字符串文字的末尾复制的,而是由内部添加的std::string

作为@songyuanyao提到了他的答案,这样做的结果是myString[myString.size()];回报'\0'

那么,为什么std::string要在字符串末尾分配空终止符呢?它当然不必支持它,因为您可以添加'\0'到字符串中,并且它包含在字符串中:

std::string myString;
myString.size();              // 0
myString.push_back('\0');
myString.size();              // 1
Run Code Online (Sandbox Code Playgroud)

此行为的原因是为了支持该std::string::c_str()功能。该c_str()函数需要返回以null结尾的const char *。最有效的方法是简单地返回一个指向内部缓冲区的指针,但是为了做到这一点,内部缓冲区必须在字符串末尾包含一个空终止符。从C ++ 11开始,字符串必须包含null终止符以支持此操作。

PS虽然不是严格地属于您的问题的一部分,但应指出,如果您的字符串中包含空字符,则来自问题的循环可能不会返回完整的字符串:

std::string S("Hey");
S.push_back('\0');
S.append("Jude");

for(int i = 0; S[i] != '\0'; ++i)
    std::cout << S[i];

// Only "Hey" is printed!
Run Code Online (Sandbox Code Playgroud)