在C++ Primer, Fifth edition中,条款3.2.1下的表3.1指出:
string s3("value")
-> s3是字符串文字的副本,不是 包括空值。
我对此的解释是-当我们初始化string s1("value");
之类的字符串时,变量s1
包含字符串value
的副本无 {{ 1}}末尾的字符。
NUL
那么,此程序是否由于#include <iostream>
using std::cin;
using std::string;
using std::cout;
using std::endl;
int main(void)
{
string s1("value");
cout << s1 << endl; // prints - value
}
没有s1
终止符而调用UB,而我们正在打印字符串?
我之所以这样问是因为,在C语言中,尝试打印不带NUL
终止符的c字符串会产生UB。 C ++中的字符串以NUL
结尾是否不是强制性的?
我在这里想念什么?
答案 0 :(得分:3)
不是强制C ++中的字符串以NUL结尾吗?
取决于“字符串”的含义。 std::string
不能以nul字符结尾,因为长度是已知的/已存储的。 char*
返回的C样式字符串(也称为std::string::c_str()
数组)必须以空字符结尾,因为长度未知/未存储。
答案 1 :(得分:2)
那么,此程序是否调用UB,因为s1没有NUL终止符,而我们正在打印字符串?
不。 std::string
提供了operator <<
的重载,它“做正确的事”。您不必担心。
我问这是因为尝试在没有NUL终止符的情况下打印c字符串会产生UB。 C ++中的字符串以NUL结尾不是强制性的吗?
这取决于您所使用的C ++ 98/03标准的版本,并不需要在字符串末尾添加空终止符,但是c_str
基本上迫使您这样做。尽管C ++ 11和更高版本确实可以保证在字符串数据的末尾有一个空终止符。
请注意,因为std::string
的{{1}}看起来像
operator <<
因此无论是否存在它都将起作用。实际上,由于for (size_t i = 0; i < member_variable_size; ++i)
std::cout << member_variable_data[i]
可以在其中嵌入空值,因此它将非常正确地进行打印,就像如何
std::string
打印
int main()
{
std::string foo("h\0ell\0o", 7);
std::cout << foo;
}
答案 2 :(得分:1)
我在这里想念什么?
This运算符重载,它以std::string
作为第二个参数。因此,std::cout << s1
不会在没有空终止符的情况下打印c字符串,您正在调用函数operator <<
并将s1
传递给它。
那么,此程序是否因为
s1
没有NUL终止符而调用UB,而我们正在打印字符串?
通常,您可以依赖所使用的标准库背后的开发人员的能力,即,使用此重载运算符对我来说似乎很安全:)