我测试了这段代码:
#include <iostream>
#include <cstdio>
#include <string>
using namespace std;
int main()
{
string s1("a"),s2("b");
const char * s = (s1+s2).c_str();
printf("%s\n",s);
}
Run Code Online (Sandbox Code Playgroud)
它返回"ab".
据我所知,因为它(s1 +s2)是一个临时对象,可能会以某种方式消失(我不知道),然后const char * s可能指向未定义的内存并可能被转储.
那么使用.c_str()那样安全吗?
650*_*502 57
在你的例子中它并不安全.然而,这是安全的
printf("%s\n", (a + b).c_str());
Run Code Online (Sandbox Code Playgroud)
原因是a + b在完整表达式结束时销毁临时值(如结果).在您的示例中,const char *幸存的包含临时的完整表达式和解除引用它是未定义的行为.
"未定义行为"中最糟糕的部分是事情可能显然仍然有效......(只有当你在包括你父母在内的广大受众面前制作你的演示时,UB代码才会崩溃;-))
Pie*_*aud 29
在那个例子中,我们可以引用标准:
12.2临时对象[class.temporary]
临时对象作为评估全表达式(1.9)的最后一步被销毁,该表达式(词法上)包含创建它们的点.即使该评估以抛出异常结束,也是如此.销毁临时对象的值计算和副作用仅与完整表达相关联,而不与任何特定子表达相关联.
这是你的分号后面的分号:
const char * s = (s1+s2).c_str(); // <- Here
Run Code Online (Sandbox Code Playgroud)
所以在这里:
printf("%s\n",s); // This line will now cause undefined behaviour.
Run Code Online (Sandbox Code Playgroud)
为什么?因为当你的物体被毁坏时,你现在不知道这个地方到底是什么了......
这里的坏处是,使用Undefined行为,你的程序似乎在第一次工作,但是...它会在最糟糕的时候崩溃...
你可以做:
printf( "%s\n", (s1+s2).c_str() );
Run Code Online (Sandbox Code Playgroud)
它会起作用,因为对象还没有被破坏(记住,在分号之后......).
这不安全,但您可以轻松地分配给一个新变量,并且指针在该变量的范围内是安全的:
string s1("a"), s2("b") , s3;
s3 = s1 + s2;
printf("%s\n", s3.c_str());
//other operations with s3
Run Code Online (Sandbox Code Playgroud)