8

为什么你可以在 std::basic_string 中插入一个 '\0' 字符并且 .length() 方法不受影响,但是如果你调用char_traits<char>::length(str.c_str())你会得到字符串的长度直到第一个 '\0' 字符?

例如

string str("abcdefgh");
cout << str.length(); // 8
str[4] = '\0';
cout << str.length(); // 8
cout << char_traits<char>::length(str.c_str()); // 4
4

1 回答 1

18

好问题!

原因是 C 风格的字符串被定义为以空字节结尾的字节序列。当您使用.c_str()从 C++ 中获取 C 风格的字符串时std::string,您将返回 C++ 字符串存储的序列,其后有一个空字节。当你将它传递给 时strlen,它会扫描字节直到它遇到一个空字节,然后报告它在此之前找到了多少个字符。如果string包含一个空字节,那么strlen将报告一个小于字符串整个长度的值,因为它会在到达字符串的真正结尾之前停止。

一个重要的细节是strlenchar_traits<char>::length不是同一个功能。但是,(第 21.1.1 节)的 C++ ISO 规范char_traits<charT>::lengthchar_traits<charT>::length(s)返回的是最小 i的,这char_traits<charT>::eq(s[i], charT())是正确的。对于char_traits<char>,该eq函数只是通过比较返回两个字符是否相等==,并且通过写入构造一个字符char()会产生一个空字节,因此这等于说“字符串中的第一个空字节在哪里?” 它本质上是如何strlen工作的,尽管两者在技术上是不同的功能。

但是, C++std::string是“任意字符序列”的更一般概念。它的实现细节对外界是隐藏的,尽管它可能由开始和停止指针或指针和长度表示。因为这种表示不依赖于存储的字符,所以询问std::string它的长度会告诉你有多少字符,而不管这些字符实际上是什么。

希望这可以帮助!

于 2011-03-16T00:15:33.637 回答