绑定到静态常量引用的右值的生存期

Lifetime of rvalue bound to static const reference

提问人:sbi 提问时间:7/14/2015 最后编辑:sbi 更新时间:7/14/2015 访问量:654

问:

考虑一下:

std::string foo();

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

我知道第一次调用 生成的字符串的生存期将延长到 的生存期。foo()r1

但是,临时绑定呢?它会一直存在到范围结束,还是在重新输入时仍然存在?r2bar()

注意:我不感兴趣的是某个特定的编译器是否这样做。(我对我们使用的那个很感兴趣,我可以很容易地用它来测试。我想知道标准对此有何规定。

C++ 参考 临时

评论

2赞 Serge Rogatch 7/14/2015
独立于答案,这似乎是一种糟糕的编码风格,因此,对于好的编码风格,问题永远不会出现。
1赞 Melebius 7/14/2015
@SergeRogatch 你应该说用什么来代替。
2赞 Lightness Races in Orbit 7/14/2015
@Melebius:只有当实际目标被陈述出来时,才有可能这样做。
1赞 Lightness Races in Orbit 7/14/2015
这完全是微不足道的,无法亲自测试......

答:

7赞 Lightness Races in Orbit 7/14/2015 #1

临时值将延长到参照的生存期

[C++14: 12.2/5]: 引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象在引用的生存期内保持不变,但以下情况除外

  • 在构造函数的 ctor-initializer (12.6.2) 中,与引用成员的临时绑定将持续到构造函数退出。
  • 在函数调用 (5.2.2) 中,与引用参数的临时绑定将持续到包含调用的完整表达式完成为止。
  • 函数返回语句 (6.6.3) 中临时绑定到返回值的生存期不会延长;临时值在 return 语句中完整表达式的末尾销毁。
  • 与 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
    

—结束示例 ] [ 注意:这可能会引入悬空引用,鼓励实现在这种情况下发出警告。——尾注]

(特别要注意的是,没有一个要点与此方案匹配。

因此,在这种情况下,基本上是直到程序结束。

当然,我们可以非常简单地测试这一点:

#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";
}

结果:

main()
ctor
bye
dtor

(现场演示)