与const引用关联的临时对象的生命周期(方法链接)

时间:2015-09-01 16:41:44

标签: c++ reference lifetime

考虑以下代码snipet:

#include <iostream>

struct S {
    ~S() { std::cout << "dtor\n"; }
    const S& f(int i) const { std::cout << i << "\n"; return *this; }
};

int main() {
    const S& s = S(); 
    s.f(2);
}

Output

2
dtor

即。对象生命周期通过引用扩展,在Herb的article中解释。

但是,如果我们只更改一行代码并写入:

const S& s = S().f(1);

对已经销毁的对象进行f(2)调用:

Output

1
dtor
2

为什么会这样? f()的返回值不是正确的“时间性”类型吗?

2 个答案:

答案 0 :(得分:4)

当你写一个函数时......

const S& f(int i) const { std::cout << i << "\n"; return *this; }

...您指示编译器返回const S&,并且您负责确保引用的对象具有适合调用者使用的生命周期。 (“确保”可能构成记录客户使用情况,与您的设计一致。)

通常 - 通常将代码分离为标头和实现文件 - f(int) const的实现在调用代码时甚至都不可见,在这种情况下,编译器无法了解哪些{{1}可能会返回引用,也不会返回S是否是临时引用,因此没有依据可以决定是否需要延长生命周期。

除了显而易见的选项(例如,信任客户编写安全代码,按值或智能指针返回),还值得了解一个更加模糊的选项......

S

在函数体重载const S& f(int i) const & { ...; return *this; } const S f(int i) const && { ...; return *this; } 之前的&&&,以便在f可移动时使用&&版本,否则*this版本使用1}}版本。这样,绑定到期对象的&const &的人将绑定到对象的新副本,并根据本地f(...)引用延长生命周期,而当对象时尚未到期(尚未)const引用将是原始对象(只要引用仍然不能保证直播 - 需要一些注意事项)。

答案 1 :(得分:3)

  

为什么会这样? f()的返回值是不是正确类型&#34;暂时性&#34;?

是的,不是。这是一个有点争议的问题:官方定义&#34;暂时性&#34;有点开放。

在最近的编译器中,时间性一直在扩大。首先,它仅适用于prvalue(非 - &#34;引用&#34;)表达式,以及应用于此类表达式的成员访问(&#34;点运算符&#34;)。现在它也适用于强制转换表达式和数组访问。虽然您可以将移动操作编写为static_cast< T && >( t ),这将保留时间性,但只需编写std::move( t )即可。

我正在使用series proposals来扩展C ++,以便您的示例按预期工作。这个功能在C ++ 17中出现的可能性非常小。