5

为什么 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

4 回答 4

8

为什么标准允许跟随?

因为设计 C++ 字符串的人决定应该允许这样的事情。我不确定设计 C++ 字符串的团队中是否有人在 SO 上……但既然你自己说标准允许它,那就是它的方式,我怀疑它即将改变。

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

于 2013-07-01T11:18:52.423 回答
4

不知道这里有什么问题。

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

如果您想知道这个字符串有多少个字符被视为以空字符结尾的字符串,请使用

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带指针替换的动态数组以及std::array(C++11) 作为标准 C 数组替换.

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

于 2013-07-01T21:27:28.737 回答
2

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

于 2013-07-01T11:14:29.583 回答
1

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

于 2015-05-12T07:09:41.343 回答