将'\ 0'添加到std :: string时出现意外行为

时间:2013-07-01 11:09:58

标签: c++ string stl

为什么C ++标准允许以下内容?

#include <iostream>
#include <string>    

int main()
{
    std::string s(10, '\0'); // s.length() now is 10
    std::cout << "string is " << s << ", length is " << s.length() << std::endl;
    s.append(5, '\0'); // s.length() now is 15 
    std::cout << "string is " << s << ", length is " << s.length() << std::endl;
    // the same with += char and push_back 

    // but:
    s += "hello"; // s.length() returns 20 string is "hello"
    std::cout << "string is " << s << ", length is " << s.length() << std::endl;

    return 0;
}

为什么要加0并计算呢? 它看起来像字符串的完整性,不是吗?但我检查了标准,这是正确的行为。

4 个答案:

答案 0 :(得分:6)

  

为什么标准允许跟随?

因为设计C ++字符串的人决定应该允许这样的事情。我不确定那些设计C ++字符串的团队是否属于某个人......但是既然你自己说标准允许它,那就是它的样子,我怀疑它是否会改变。

有一个可以包含“任何东西”的字符串有时候很实用。当我不得不解决C样式字符串不能包含零字节的事实时,我可以想到一些实例。除了长C风格的字符串需要很长时间才能找到它的长度之外,C ++字符串的主要好处是它们不仅限于“你可以放入它们的内容” - 这在我的书中是件好事。

答案 1 :(得分:4)

不确定这里有什么问题。

'\0'的中间添加std::string不会改变任何内容 - null字符将被视为任何其他字符。唯一可以改变的是,如果您使用.c_str()函数接受以null结尾的字符串。但是这不是.c_str()的问题,只有特殊处理'\0'的函数。

如果您想知道该字符串有多少字符就像处理以null结尾的字符串一样,请使用

size_t len = strlen(s.c_str());

请注意,这是O(n)操作,因为这是strlen的工作原理。

如果你问为什么+=运算符没有将字符串文字"hello"的隐式空字符添加到字符串中,我说反向(添加它)不清楚,绝对不是你想要的99 % 的时间。另一方面,如果要将'\0'添加到字符串中,只需将其作为缓冲区附加:

char buffer[] = "Hello";
s.append(buffer, sizeof(buffer));

或(甚至更好)完全删除char数组和以null结尾的字符串,并使用C ++样式替换(如std::string作为NTS替换,std::vector<char>作为连续缓冲区,std::vector as指针替换的动态数组,std::array(C ++ 11)作为标准C数组替换。

另外,(正如@AdamRosenfield在评论中所提到的),添加"hello"后的字符串实际上有20个字符,可能只是你的终端没有打印空值。

答案 2 :(得分:2)

NUL char '\0'c style string的结束字符,而不是std::string s。但是,它支持此字符从const char指针获取值,以便它可以找到c样式字符串的结尾。否则,它会像其他字符一样对待

答案 3 :(得分:0)

std :: string更像是一个容器,而不是其他任何东西,\ 0是一个字符。作为一个真实的例子,请看一下Windows中的CreateProcess函数。 lpEnvironment参数采用以null结尾的以空字符结尾的字符串块(即A=1\0B=2\0C=3\0\0)。如果您正在构建一个块,那么使用std :: string会很方便。