右值绑定到静态const引用的生命周期

Lifetime of rvalue bound to static const reference

本文关键字:引用 生命 周期 const 静态 绑定      更新时间:2023-10-16

考虑一下:

std::string foo();
void bar() {
         const std::string& r1 = foo();
  static const std::string& r2 = foo();
}

我知道第一次调用foo()产生的字符串的生命周期将扩展到r1的生命周期。

那么临时绑定到r2又如何呢?它会一直存在到作用域结束,还是在重新进入bar()时仍然存在?

注意:我对特定编译器是否这样做不感兴趣。(我对我们使用的那个很感兴趣,我可以很容易地用它进行测试。)我想知道标准是怎么说的。

临时扩展到引用的生存期。

[C++14: 12.2/5]: 引用绑定到的临时对象或引用绑定到的子对象的完整对象的临时对象在引用的生命周期内持续存在,除了:

  • 在构造函数的参数初始化式(12.6.2)中,对引用成员的临时绑定将一直持续到构造函数退出为止。
  • 函数调用(5.2.2)中与引用形参的临时绑定一直存在,直到包含该调用的完整表达式完成为止。
  • 在函数返回语句(6.6.3)中,临时绑定到返回值的生存期不被延长;在返回语句的完整表达式末尾销毁临时变量。
  • new-initializer(5.3.4)中的引用的临时绑定一直存在,直到包含new-initializer完整表达式完成为止。(例子:

    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][注意:这可能会引入一个悬空引用,在这种情况下,鼓励实现发出警告。

(特别要注意,没有一个项目符号与此场景匹配。)

因此,在本例中,它实际上是直到程序结束。

当然,我们可以非常简单地测试一下:
#include <iostream>
struct Tracked
{
    Tracked() { std::cout << "ctorn"; };
    Tracked(const Tracked&) { std::cout << "copyn"; };
    ~Tracked() { std::cout << "dtorn"; };
};
void foo()
{
    static const Tracked& ref = Tracked();
}
int main()
{
    std::cout << "main()n";
    foo();
    std::cout << "byen";
}
结果:

main ()


男星
再见
井底扭矩

(现场演示)