临时参数值什么时候超出范围?

Jam*_*ton 19 c++

可能重复:
临时生活

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());
Run Code Online (Sandbox Code Playgroud)

可以轻松地重写上面的示例以使用智能指针而不是字符串; 我多次遇到过这两种情况.无论如何,上面的例子将在ModernFunction中构造一个STL字符串,返回它,然后获取一个指向字符串对象内部的C风格字符串的指针,然后将该指针传递给遗留函数.

  1. 在返回ModernFunction之后,存在一个临时字符串对象.什么时候超出范围?
  2. 编译器是否可以调用c_str(),破坏此临时字符串对象,然后将悬空指针传递给LegacyFunction?(请记住,字符串对象正在管理c_str()返回值指向...的内存.
  3. 如果上面的代码不安全,为什么它不安全,并且有一种更好,同样简洁的方法来编写它而不是在进行函数调用时添加一个临时变量?如果它安全,为什么?

For*_*veR 15

LegacyFunction(ModernFunction().c_str());
Run Code Online (Sandbox Code Playgroud)

复制的破坏将在评估之后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
{ }
}
Run Code Online (Sandbox Code Playgroud)


Ste*_*sop 9

在返回ModernFunction之后,存在一个临时字符串对象.什么时候超出范围?

严格来说,它从不范围内.范围是名称的属性,而不是对象.事实上,自动变量在范围生命周期之间具有非常紧密的关联.非自动变量的对象是不同的.

临时对象在它们出现的完整表达式的末尾被销毁,这里有一些与此无关的例外.无论如何,特殊情况延长了临时的寿命,它们并没有减少它.

是否有可能编译器调用c_str(),破坏此临时字符串对象,然后将悬空指针传递给LegacyFunction

不,因为全表达式是LegacyFunction(ModernFunction().c_str())(不包括分号:感觉那个迂腐),所以作为返回值的临时值在ModernFunctionLegacyFunction返回之前不会被销毁.

如果它安全,为什么?

因为临时的寿命足够长.

总的来说c_str,你必须担心两件事.首先,如果字符串被销毁,它返回的指针将变为无效(这就是你所要求的).其次,如果修改了字符串,它返回的指针将变为无效.你没有在这担心,但没关系,因为没有任何东西可以修改字符串.