("Some extra info \n" + errorMessage())
is a 暂时的 std::string
。这意味着,语句完成后,它的生命周期就结束了。
cout << ("Some extra info \n" + errorMessage()).c_str() << endl
有效,因为此时std::cout
使用std::string
它的生命周期还没有结束。这
<< message
不过,部分是未定义的行为。纯粹是运气好,它能起作用。
要解决该问题,您需要扩展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();
现在您可以根据需要对它们进行操作。
另一种方法是
std::string str = "Some extra info \n" + errorMessage();
但是,如果编译器不执行某些操作返回值优化 https://stackoverflow.com/questions/12953127/what-are-copy-elision-and-return-value-optimization,这将导致一个构造函数and复制构造函数 (very bad)或移动构造函数(>= C++11,更好,但不必要)被执行。
BTW, this exact issue is even covered in "The C++ Programming Language" 4th Edition!
在第 10.3.4 节“临时对象”中,Stroustrup 先生写道:
标准库字符串有一个成员c_str()
(§36.3) 返回一个指向以零结尾的字符数组的 C 风格指针
(第 2.2.5 条、第 43.4 条)。另外,运营商+
被定义为字符串
级联。这些对于字符串来说是有用的工具。然而,在
它们的组合可能会导致难以理解的问题。例如:
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
- 声明有点微妙。这
条件将按预期工作,因为其中的完整表达式
临时持有s2+s3
被创造就是条件本身。
但是,该临时对象会在受控语句之前被销毁
输入,所以任何使用cs
不能保证工作。
因此,不必担心您的 C++ 技能。甚至 C++ 圣经也解释了这一点。 ;-)