C++11中向std::string插入空终止符后遍历全长度是否合法?
C++11 std::string 存储空终止符及遍历问题解答
结论
C++11 标准完全允许 std::string 存储空终止符('\0'),也支持按实际存储长度遍历整个字符串。
std::string 内部单独维护了长度计数,不会将 '\0' 作为字符串结束标志,'\0' 对它来说就是普通的 ASCII 0 字符,和其他字符没有任何区别。
测试代码说明
你给出的测试代码存在构造逻辑问题:
#include <string> #include <iostream> int main(int argc, char** argv) { std::string s("\0\0hello\0world\n"); for (char c : s) { std::cout << " " << (unsigned int)c; } std::cout << std::endl; return 0; }
上述代码中std::string s("\0\0hello\0world\n")使用了接收C风格字符串const char*的构造函数,默认会以第一个遇到的'\0'作为输入字符串的结束标志,最终构造出来的s长度为0,范围for循环不会输出任何内容。
如果要正确构造包含多个'\0'的字符串,需要显式指定输入字符串的总长度,修改方式如下:
// 总长度计算:2个'\0' + "hello"(5) + 1个'\0' + "world"(5) + '\n'(1) = 14 std::string s("\0\0hello\0world\n", 14);
修改后运行代码,遍历会输出所有字符的ASCII码,包含开头和中间的'\0',输出结果为:
0 0 104 101 108 108 111 0 119 111 114 108 100 10
补充注意点
- 调用
c_str()或data()(C++11起两者等价)成员函数时,返回的C风格字符串末尾会自动追加一个额外的'\0',这个追加的字符不计入size()的返回值。 - 所有
std::string的原生成员接口(substr、find、赋值、比较等)都会按实际存储长度处理,只有当你把std::string传入接收C风格字符串的函数(比如strlen、printf("%s")等)时,才会被'\0'截断。
内容的提问来源于stack exchange,提问作者pico
相关产品推荐
相关产品推荐

