从函数返回的对象的延长生命周期

时间:2017-04-11 15:09:49

标签: c++ reference language-lawyer lifetime temporary

关于从函数返回并绑定到rvalue / const左值引用的对象的生命周期延长,我有一些不清楚的信息。来自here的信息。

  

不会扩展对return语句中函数返回值的临时绑定:它会在返回表达式的末尾立即销毁。这样的函数总是返回一个悬空引用。

如果我理解正确,引用声称返回语句返回的对象的生命周期是不可扩展的。但最后一句话表明,它只适用于返回引用的函数 在GCC上,从下面的代码我得到以下输出:

struct Test
{
  Test() { std::cout << "creation\n"; }
  ~Test() { std::cout << "destruction\n"; }
};

Test f()
{
    return Test{};   
}

int main()
{
    std::cout << "before f call\n";
    Test && t = f();
    std::cout << "after f call\n";
}
before f call
creation
after f call
destruction

所以看起来生命延长了 是否应延长与此类参考相关的临时对象的生命周期?您还可以提供更明确的信息来源吗?

2 个答案:

答案 0 :(得分:7)

  

所以看起来生命延长了。

代码非常有效,但请注意,生命周期扩展的对象不是f()在函数Test{}内创建的临时对象,它是函数{{1}返回的对象}。返回的对象是从临时对象移动构造的,然后绑定到f()并延长生命周期。 BTW返回的对象是按值返回的,它也是一个临时对象。

对于观察,您可以手动添加移动构造函数:

t

使用禁止copy elision模式编译并运行,结果是:

struct Test
{
  Test() { std::cout << "creation\n"; }
  ~Test() { std::cout << "destruction\n"; }
  Test(Test&&) { std::cout << "move\n"; }
};

LIVE

标准引用§15.2/6 Temporary objects [class.temporary]

  

引用绑定的临时值或临时值   引用绑定到的子对象的完整对象   在参考文件的生命周期内持续存在,除了:

     

(6.1)绑定到函数中引用参数的临时对象   调用持续到包含完整表达式完成   电话。

     

(6.2)临时绑定到返回值的生命周期   函数return语句未扩展;临时被摧毁   在return语句中的完整表达式的末尾。

     

(6.3)新建初始化程序中对引用的临时绑定仍然存在   直到包含完整表达式的完成   新初始化。 [实施例:

before f call
creation      // the temporary created inside f
move          // return object move-constructed
destruction   // the temporary destroyed
after f call
destruction   // the returned object destroyed
     

- 结束示例] [注意:这可能会引入一个悬空参考,和   鼓励实现在这种情况下发出警告。    - 结束说明]

答案 1 :(得分:0)

GOTW article

引用
  

临时对象只会持续到它出现的完整表达式的结尾。但是,C ++故意指定将临时对象绑定到对堆栈上的const(或ravlue引用)的引用会延长临时对生命周期的生命周期,从而避免了常见的悬空引用错误。 。

string f() { return "abc"; }

void g() {
const string& s = f();
  cout << s << endl;    // can we still use the "temporary" object?
}
  

在上面的示例中,f()返回的临时值一直持续到结束大括号。 (注意,这仅适用于基于堆栈的引用。它不适用于作为对象成员的引用。)

对于法律术语,请阅读this SO answer

答案适用于 本地const引用和rvalue引用