使用“空”字符数组中的构造函数时,C++ 错误的 std::string 长度

Ale*_* B. -1 c++ arrays string string-length

我在不同的编译器上测试了这个代码片段,但总是得到相同的结果,但我就是不明白为什么。

unsigned char buffer[0x4000] = {0};
string strText((char*)buffer, 0x4000);  
cout << "strlen((char*)buffer) = " << strlen((char*)buffer) << endl;;
cout << "strText.length() = " << strText.length() << endl;
Run Code Online (Sandbox Code Playgroud)

输出是:

strlen((char*)buffer) = 0
strText.length() = 16384
Run Code Online (Sandbox Code Playgroud)

我正在std::stringunsigned char数组创建一个变量(您也可以使用有符号的字符数组,结果是相同的)。在将变量传递给字符串构造函数之前,数组内容被“清零”(根据情况使用 memset 或 C++ 数组初始化)。

如果使用 C 样式函数获取字符串长度strlen((char*)buffer),则结果如预期为“0”。

如果使用方法获取字符串对象的长度,则string::length()该值等于字符串构造函数中传递的数组大小(本例中为 16384)。为什么?

另外,作为副作用,如果使用打印字符串对象的内容,std::cout您会得到一个非常长的空字符串(所有“0”都被“空格”替换)。

我是否应该对 std::string 对象执行一些额外的操作以获得我期望的长度(0)?

谢谢

Ted*_*gmo 6

您使用的构造函数是这个构造函数(引用自basic_string@ cppreference):

constexpr basic_string( const CharT* s, size_type count,
                        const Allocator& alloc = Allocator() );
Run Code Online (Sandbox Code Playgroud)

count用 指向的字符串的第一个字符构造字符串ss可以包含空字符。字符串的长度是count[s, s + count)如果不是有效范围,则行为未定义。


你问:

如果使用 string::length() 方法获取字符串对象的长度,则该值等于字符串构造函数中传递的数组大小(本例中为 16384)。为什么?

因为您向构造函数提供了长度std::string,并且正如 wiki 所说,可以包含空字符。

我是否应该对 std::string 对象执行一些额外的操作以获得我期望的长度(0)?

是的,这将是一个默认构造的std::string. 只需在构建时删除buffer和 长度std::string

constexpr basic_string( const CharT* s, size_type count,
                        const Allocator& alloc = Allocator() );
Run Code Online (Sandbox Code Playgroud)

另一方面,如果您希望strText保留空间等于缓冲区的空间,请调用成员函数reserve

std::string strText;
strText.reserve(sizeof buffer);
std::cout << strText.length() << '\n'; // prints 0
Run Code Online (Sandbox Code Playgroud)

如果您strText只想获得直到第一个空字符为止的长度buffer,请在构造时排除长度 ( count) strTextstd::string构造函数将读取直到\0找到 a 为止,并且strText.length()0在您的情况下:

std::string strText;
Run Code Online (Sandbox Code Playgroud)