αλε*_*λυτ 9 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);
}
Run Code Online (Sandbox Code Playgroud)
输出:
2
dtor
Run Code Online (Sandbox Code Playgroud)
即对象的生命周期通过引用扩展,这在Herb的文章中有所解释.
但是,如果我们只更改一行代码并写入:
const S& s = S().f(1);
Run Code Online (Sandbox Code Playgroud)
f(2)对已经被摧毁的物体的召唤:
输出:
1
dtor
2
Run Code Online (Sandbox Code Playgroud)
为什么会这样?是f()的返回值不是一个正确的类型'暂时性’的?
当你这样编写一个函数时......
const S& f(int i) const { std::cout << i << "\n"; return *this; }
Run Code Online (Sandbox Code Playgroud)
...您指示编译器返回 aconst S&并且您负责确保引用的对象具有适合调用者使用的生命周期。(“确保”可能构成记录与您的设计正常配合的客户端使用情况。)
通常,通过将代码典型地分离为标头和实现文件,f(int) const调用代码甚至看不到实现,在这种情况下,编译器无法了解S可能返回的引用,也无法了解该引用是否S是临时的。是否需要延长寿命没有依据。
除了明显的选项(例如,信任客户端编写安全代码、按值返回或智能指针)之外,值得了解一个更晦涩的选项......
const S& f(int i) const & { ...; return *this; }
const S f(int i) const && { ...; return *this; }
Run Code Online (Sandbox Code Playgroud)
和紧接在函数体重载之前,如果可移动则使用版本,否则&使用版本。这样,将 a 绑定到在过期对象上调用的人将绑定到该对象的新副本,并根据本地引用延长生命周期,而当对象尚未过期时,引用将指向原始对象(仍然不能保证与参考一样长的寿命 - 需要一些谨慎)。&&f&&*this&const &f(...)constconst