c++ std::strings在初始化为字符串时是否以'\0'结尾?

6gpjuf90  于 2023-08-09  发布在  其他
关注(0)|答案(3)|浏览(134)

我知道字符串对象不以null结尾,但为什么这样做会有效呢?

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

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

eqfvzcg8

eqfvzcg81#

所以构造函数也复制了空终止符,但不增加长度?
正如您所知,std::string不包含空字符(并且它不会在这里复制空字符)。
关键是您使用的是std::basic_string::operator[]。根据C++11,当指定的索引等于size()时,std::basic_string::operator[]将返回空字符。
如果是pos == size(),则返回对值为CharT()的字符(空字符)的引用。
对于第一个(非常量)版本,如果此字符被修改为除charT()以外的任何值,则行为未定义。

w7t8yxp5

w7t8yxp52#

std::string在内部以null终止的C字符串形式存储数据,但在正常使用中不允许访问null终止符。
例如,如果我将值“Hello,World!“转换为字符串,则内部缓冲区将如下所示:

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

// Internal Buffer...
// [ H | e | l | l | o | , |   | W | o | r | d | ! | \0 ]
//                                                   ^ Null terminator.

字符串
在这个例子中,null终止符不是从字符串文字的末尾复制的,而是由std::string在内部添加的。
正如@songyuanyao在他的回答中提到的,这样做的结果是myString[myString.size()];返回'\0'
那么,为什么std::string要在字符串的末尾分配一个null终止符呢?它当然不需要支持一个,因为你可以将'\0'添加到一个字符串中,并且它包含在字符串中:

std::string myString;
myString.size();              // 0
myString.push_back('\0');
myString.size();              // 1


此行为的原因是为了支持std::string::c_str()函数。c_str()函数需要返回一个空终止的const char *。最有效的方法是简单地返回一个指向内部缓冲区的指针,但是为了做到这一点,内部缓冲区必须在字符串的末尾包含一个空终止符。从C++11开始,字符串 * 必须 * 包含空终止符来支持这一点。
P.S.虽然不是你的问题的严格部分,但应该指出的是,如果你的字符串包含空字符,那么你的问题的循环可能不会返回完整的字符串:

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!

gmol1639

gmol16393#

*std::string重载:std::string类有一种特殊的方式来存储它的长度,所以它不需要像C风格的字符串那样使用空终止。您可以使用S[i]直接访问字符,并且该循环在没有'\0'的情况下也可以工作。
*高效处理:std::string构造函数在创建字符串时不添加null终止符,因为它使用了更智能的长度管理方法。这种方法对于处理和操作字符串更有效。

相关问题