可能重复:
Lifetime of temporaries
int LegacyFunction(const char *s) {
// do something with s, like print it to standard output
// this function does NOT retain any pointer to s after it returns.
return strlen(s);
}
std::string ModernFunction() {
// do something that returns a string
return "Hello";
}
LegacyFunction(ModernFunction().c_str());
上面的例子很容易被重写,以使用智能指针而不是字符串;我多次遇到过这两种情况。无论如何,上面的例子将在ModernFunction中构造一个STL字符串,返回它,然后获取一个指向字符串对象内部的C风格字符串的指针,然后将该指针传递给遗留函数。
答案 0 :(得分:15)
LegacyFunction(ModernFunction().c_str());
在评估full expression
之后(即从LegacyFunction
返回后),销毁副本。
n3337 12.2 / 3
临时对象作为最后一步被销毁 在评估全表达式(1.9)时(词法上)包含创建它们的点。
n3337 1.9 / 10
完整表达式是不是另一个表达式的子表达式的表达式。如果是语言结构 被定义为产生函数的隐式调用,语言构造的使用被认为是一种 表达用于此定义的目的。对生命周期结束时生成的析构函数的调用 临时对象以外的对象是隐式完整表达式。转换应用于结果 表达式,以满足表达式出现的语言结构的要求 也被认为是完整表达的一部分。 [例如:
struct S { S(int i): I(i) { } int& v() { return I; } private: int I; }; S s1(1); // full-expression is call of S::S(int) S s2 = 2; // full-expression is call of S::S(int) void f() { if (S(3).v()) // full-expression includes lvalue-to-rvalue and // int to bool conversions, performed before // temporary is deleted at end of full-expression { } }
答案 1 :(得分:9)
在返回ModernFunction之后,存在一个临时字符串对象。什么时候超出范围?
严格来说,它永远不会在范围内。范围是名称的属性,而不是对象。事实上,自动变量在范围和生命周期之间具有非常紧密的关联。非自动变量的对象是不同的。
临时对象在它们出现的完整表达式的末尾被销毁,但有一些与此无关的例外。无论如何,特殊情况延长临时的生命周期,他们不会减少它。
编译器是否可以调用c_str(),破坏此临时字符串对象,然后将悬空指针传递给LegacyFunction
不,因为全表达式是LegacyFunction(ModernFunction().c_str())
(不包括分号:感觉那个迂腐),所以ModernFunction
的临时值不会被销毁LegacyFunction
已经回来了。
如果安全,为什么?
因为临时的寿命足够长。
一般情况下c_str
,你必须担心两件事。首先,如果字符串被销毁,它返回的指针将变为无效(这就是你所要求的)。其次,如果修改了字符串,它返回的指针将变为无效。你没有在这担心,但没关系,因为没有修改字符串。