考虑一下:
std::string foo();
void bar() {
const std::string& r1 = foo();
static const std::string& r2 = foo();
}
我知道第一次调用foo()
后产生的字符串的生命周期将延长到r1
的生命周期。
但r2
临时绑定怎么样?它会一直存在到范围的末尾,还是在重新进入bar()
时仍然存在?
注意:我对特定编译器是否这样做感兴趣。 (我对我们使用的那个很感兴趣,我可以轻松地测试它。)我想知道标准对此有何看法。
答案 0 :(得分:7)
临时扩展到参考的生命周期。
[C++14: 12.2/5]:
引用绑定的临时值或引用绑定到的子对象的完整对象的临时值在引用的生命周期内持续存在除强>:
- 构造函数的 ctor-initializer (12.6.2)中与引用成员的临时绑定将持续存在,直到构造函数退出。
- 函数调用(5.2.2)中的引用参数的临时绑定将持续到包含该调用的完整表达式完成为止。
- 不扩展函数返回语句(6.6.3)中返回值的临时绑定的生存期;临时在return语句中 full-expression 的末尾被销毁。
new-initializer (5.3.4)中对引用的临时绑定一直持续到包含的完整表达式完成为止新初始化。 [例如:
struct S { int mi; const std::pair<int,int>& mp; }; S a { 1, {2,3} }; S* p = new S{ 1, {2,3} }; // Creates dangling reference
-end example] [注意:这可能会引入一个悬空引用,并鼓励实现在这种情况下发出警告。 -end note]
(特别注意,没有一个项目符合这种情况。)
因此,在这种情况下,它基本上直到程序结束。
当然,我们可以非常轻松地测试这个:
#include <iostream>
struct Tracked
{
Tracked() { std::cout << "ctor\n"; };
Tracked(const Tracked&) { std::cout << "copy\n"; };
~Tracked() { std::cout << "dtor\n"; };
};
void foo()
{
static const Tracked& ref = Tracked();
}
int main()
{
std::cout << "main()\n";
foo();
std::cout << "bye\n";
}
结果:
主()
构造函数
再见
析构函数