根据这个问题的答案,表达式中创建的临时对象持续整个表达式。这似乎意味着我们可以通过 const 引用多次将临时值传递到函数中并从函数中返回它,而无需获得悬空引用,只要它位于同一表达式内即可。像这样的东西:
#include <iostream>
#include <string>
using std::string;
const int& foo(const int& i) {
std::cout << i << "\n";
return i;
}
int main(void) {
foo(foo(foo(foo(foo(foo(100))))));
// every instance of foo receives valid reference?
return 0;
}
然而,这个问题引用的标准如下:
函数调用 (5.2.2) 中对引用参数的临时绑定将持续存在,直到包含调用的完整表达式完成为止。
答案之一是“这意味着直到右大括号,即}”,暗示“完整表达式”指的是函数体,这意味着在上面的示例中,临时创建的生命周期对于文字 100 应该只持续到第一次调用
foo
结束。
问题:
上例中对
foo
的任何调用是否使用悬空引用?
临时100的寿命是多少?它是仅扩展到第一次调用
foo
的参数的生命周期,还是主函数的整个第一行?
如果我要修改
main
的第一行:
const int &a = foo(100);
临时的什么时候销毁?从
foo
返回之后(但在分配给 a
之前,或者分配给 a
之后(即仅在这一行之后)?
这意味着直到右大括号
指的是参考生命周期延长,他们所指的大括号是
main
末尾的那个。
代码中临时
100
的生命周期将持续到最后一次 foo
调用之后,因为所有调用都是同一表达式的一部分。如果将结果分配给引用,则生命周期将延长至 main
: 的末尾
int main(void) {
const int& a = foo(foo(foo(foo(foo(foo(100))))));
std::cout << "a valid reference: " << a << "\n";
return 0;
}