临时寿命延长是通过将引用变量直接绑定到临时变量实现的,但不仅如此。关于临时寿命延长的详细列表,请参见规范:
[class.temporary]。
HolyBlackCat大神提供的答案非常好,但我觉得需要一些示例。
⦿ 直接绑定临时变量
// function prototype
std::string foo()
// calling foo:
const auto& b = foo()
// also, similarly:
const std::string& s = "hi"
根据语言规则,在以下情况下也可以实现临时生命周期的延长:
⦿ 括号 ( ) (分组,而非函数调用)
const auto& a = (foo())
const std::string& s = ("hello "s + "world")
对于接下来的案例,让我们添加以下结构体:
struct A {
std::string str = "hey";
int arr[3] = {2, 3, 4};
int* ptr = arr;
const auto& foo() const {
return str;
}
};
⦿ member access ., .*
const auto& b1 = A().str;
const auto& b2 = A().arr;
const auto& b3 = A().ptr;
const auto& b4 = *A().ptr;
const auto& str_ptr = &A::str;
const auto& arr_ptr = &A::arr;
const auto& ptr_ptr = &A::ptr;
const auto& c1 = A().*str_ptr;
const auto& c2 = A().*arr_ptr;
const auto& c3 = A().*ptr_ptr;
const auto& foo_ptr = &A::foo;
const auto& c4 = (A().*foo_ptr)();
⦿ 数组访问 [ ](非重载;必须使用数组而不是指针)
const auto& d1 = A().arr[0];
const auto& d2 = A().ptr[0];
const auto& d3 = A().str[0];
⦿ ternary operator ? :
const auto& e1 = true? A() : A(); // lifetime of the 1st A() is extended
const auto& e2 = false? A() : A(); // lifetime of the 2nd A() is extended
⦿ comma operator , (not overloaded)
const auto& f1 = (A(), A()); // lifetime of the 2nd A() is extended
⦿ 任何不涉及“用户自定义转换”的 any cast(可能不使用构造函数或转换运算符)
const auto& g1 = const_cast<const A&&>(A());
const double& g2 = A().arr[0];
对于不会延长生命周期的铸造,让我们添加一个额外的类:
class B {
const A& a;
public:
B(const A& a): a(a){}
};
以下转换经过用户定义的转换,因此不会延长A的生命周期:
const auto& g3 = ((B&&)A()); // lifetime of A() is NOT extended (g3 dangling)