关于从函数返回并绑定到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
所以看起来生命延长了 是否应延长与此类参考相关的临时对象的生命周期?您还可以提供更明确的信息来源吗?
答案 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"; }
};
标准引用§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)
临时对象只会持续到它出现的完整表达式的结尾。但是,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引用