rbe*_*485 3 c++ string iostream cout c-strings
我有一个方法,它返回一个字符串以显示为错误消息.根据程序中出现此错误的位置,我可能会在显示错误消息之前添加一些解释.
string errorMessage() {
return "this is an error";
}
// somewhere in the program...
const char* message = ("Some extra info \n" + errorMessage()).c_str();
cout << message << endl;
Run Code Online (Sandbox Code Playgroud)
(我将消息存储为const char*,因为我实际上会将此错误提供给另一个接受const char*参数的方法)
此时它输出垃圾(控制台上的不可打印的字符).
所以我玩了它,发现如果相反我做:
// somewhere in the program...
const char* message = ("Some extra info \n" + errorMessage()).c_str();
cout << ("Some extra info \n" + errorMessage()).c_str() << endl << message << endl;
Run Code Online (Sandbox Code Playgroud)
然后它会正确显示两次消息.
为什么提供额外的参数使其cout按我的意图工作?
cad*_*luk 12
("Some extra info \n" + errorMessage())是暂时的 std::string.这意味着,在声明完成后,它的生命周期已经结束.
cout << ("Some extra info \n" + errorMessage()).c_str() << endl
Run Code Online (Sandbox Code Playgroud)
因为在std::cout使用std::string它的生命周期尚未结束.该
<< message
Run Code Online (Sandbox Code Playgroud)
但是,部分是未定义的行为.纯粹的运气它有效.
要解决这个问题,你需要std::string使用或者const std::string&从C++ 11 开始延长它的生命周期std::string&&:
const std::string& str_const_ref = "Some extra info \n" + errorMessage();
std::string&& str_rvalue = "Some extra info \n" + errorMessage();
Run Code Online (Sandbox Code Playgroud)
现在您可以根据需要对它们进行操作.
另一种方式是
std::string str = "Some extra info \n" + errorMessage();
Run Code Online (Sandbox Code Playgroud)
但是,如果编译器没有做一些返回值优化,这将导致构造函数和复制构造函数(<C++ 11,非常糟糕)或移动构造函数(> = C++ 11,更好,但不必要)被执行.
顺便说一句,这个确切的问题甚至包含在"The C++ Programming Language" 第 4 版中!
在§10.3.4"临时对象"中,Stroustrup先生写道:
标准库字符串有一个成员
c_str()(§36.3),它返回一个C样式指针,指向一个以零结尾的字符数组(§2.2.5,§43.4).此外,运算符+被定义为字符串连接.这些是字符串的有用工具.但是,它们可能会导致模糊的问题.例如:Run Code Online (Sandbox Code Playgroud)void f(string& s1, string& s2, string& s3) { const char* cs = (s1+s2).c_str(); cout << cs; if (strlen(cs=(s2+s3).c_str())<8 && cs[0]=='a') { // cs used here } }[...]创建一个临时字符串对象来保存
s1+s2.接下来,从该对象中提取指向C样式字符串的指针.然后 - 在表达式的末尾 - 删除临时对象.但是,返回的C样式字符串c_str()被分配为临时对象保留的一部分s1+s2,并且在该临时表被销毁之后不保证该存储存在.因此,cs指向解除分配的存储.输出操作cout<<cs可能会按预期工作,但这绝对是运气.编译器可以检测并警告此问题的许多变体.if-statement 的问题有点微妙.条件将按预期工作,因为临时持有的完整表达s2+s3创造就是条件本身.但是,在输入受控语句之前,该临时文件已被销毁,因此cs无法保证其使用.
所以,不要担心你的C++技能.甚至C++圣经也解释了它.;-)
| 归档时间: |
|
| 查看次数: |
3278 次 |
| 最近记录: |