我知道字符串对象不以null结尾,但为什么这样做会有效呢?
std::string S("Hey"); for(int i = 0; S[i] != '\0'; ++i) std::cout << S[i];
字符串所以构造函数也复制了空终止符,但不增加长度?为什么会这么麻烦?
eqfvzcg81#
所以构造函数也复制了空终止符,但不增加长度?正如您所知,std::string不包含空字符(并且它不会在这里复制空字符)。关键是您使用的是std::basic_string::operator[]。根据C++11,当指定的索引等于size()时,std::basic_string::operator[]将返回空字符。如果是pos == size(),则返回对值为CharT()的字符(空字符)的引用。对于第一个(非常量)版本,如果此字符被修改为除charT()以外的任何值,则行为未定义。
std::string
std::basic_string::operator[]
size()
pos == size()
CharT()
charT()
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'添加到一个字符串中,并且它包含在字符串中:
myString[myString.size()];
'\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::c_str()
c_str()
const char *
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!
型
gmol16393#
*std::string重载:std::string类有一种特殊的方式来存储它的长度,所以它不需要像C风格的字符串那样使用空终止。您可以使用S[i]直接访问字符,并且该循环在没有'\0'的情况下也可以工作。*高效处理:std::string构造函数在创建字符串时不添加null终止符,因为它使用了更智能的长度管理方法。这种方法对于处理和操作字符串更有效。
S[i]
3条答案
按热度按时间eqfvzcg81#
所以构造函数也复制了空终止符,但不增加长度?
正如您所知,
std::string
不包含空字符(并且它不会在这里复制空字符)。关键是您使用的是
std::basic_string::operator[]
。根据C++11,当指定的索引等于size()
时,std::basic_string::operator[]
将返回空字符。如果是
pos == size()
,则返回对值为CharT()
的字符(空字符)的引用。对于第一个(非常量)版本,如果此字符被修改为除
charT()
以外的任何值,则行为未定义。w7t8yxp52#
std::string
在内部以null终止的C字符串形式存储数据,但在正常使用中不允许访问null终止符。例如,如果我将值“Hello,World!“转换为字符串,则内部缓冲区将如下所示:
字符串
在这个例子中,null终止符不是从字符串文字的末尾复制的,而是由
std::string
在内部添加的。正如@songyuanyao在他的回答中提到的,这样做的结果是
myString[myString.size()];
返回'\0'
。那么,为什么
std::string
要在字符串的末尾分配一个null终止符呢?它当然不需要支持一个,因为你可以将'\0'
添加到一个字符串中,并且它包含在字符串中:型
此行为的原因是为了支持
std::string::c_str()
函数。c_str()
函数需要返回一个空终止的const char *
。最有效的方法是简单地返回一个指向内部缓冲区的指针,但是为了做到这一点,内部缓冲区必须在字符串的末尾包含一个空终止符。从C++11开始,字符串 * 必须 * 包含空终止符来支持这一点。P.S.虽然不是你的问题的严格部分,但应该指出的是,如果你的字符串包含空字符,那么你的问题的循环可能不会返回完整的字符串:
型
gmol16393#
*
std::string
重载:std::string
类有一种特殊的方式来存储它的长度,所以它不需要像C风格的字符串那样使用空终止。您可以使用S[i]
直接访问字符,并且该循环在没有'\0'
的情况下也可以工作。*高效处理:
std::string
构造函数在创建字符串时不添加null终止符,因为它使用了更智能的长度管理方法。这种方法对于处理和操作字符串更有效。