【问题标题】:Lifetime of const reference variable not extendedconst 引用变量的生命周期未延长
【发布时间】:2023-03-21 21:24:01
【问题描述】:

将临时对象绑定到 const 引用会延长其生命周期;参看。 GotW #88.

为什么这在这个 sn-p 上不起作用?直播here

#include <iostream>
#include <string>

struct A {
    A() : s("abc") {}
    const std::string& s;
};

struct B {
    const std::string& s = "def";
};

int main() {
    A a;
    std::cout << a.s << std::endl;
    B b;
    std::cout << b.s << std::endl;
}

额外问题:如何使用 gcc 触发警告?

【问题讨论】:

  • 引用您链接的 GotW:“请注意,这仅适用于基于堆栈的引用。它不适用于作为对象成员的引用”。
  • 是的,这就是 R Sahu 在他的回答中提到的。谢谢。

标签: c++ reference lifetime string-literals


【解决方案1】:

在您链接到的文章中,您会发现:

(注意这仅适用于基于堆栈的引用。它不适用于作为对象成员的引用。)

这就是ab 中的引用无效的原因。它们不会延长临时工的寿命。

【讨论】:

  • 好久没看全文,忘记了这一点。谢谢!
  • 您知道如何为此触发警告吗?
  • 使用 g++,-Wextra 产生:warning: a temporary bound to ‘A::s’ only persists until the constructor exits [-Wextra]
  • @RSahu 如果您使用 g++ 或 MSVS 2011/2014/2017 编译此代码,它将完美编译并运行。我什至没有收到警告。我不明白什么吗?是UB吗?
  • @Nik-Lz,是的,它是 UB。
【解决方案2】:

来自 C++14 [class.temporary]/5:

引用绑定的临时对象或引用绑定的子对象的完整对象的临时对象仍然存在 对于参考除了的生命周期:

  • 临时绑定到构造函数的 ctor-initializer 中的引用成员会一直存在,直到构造函数退出。

  • [...]

【讨论】:

    【解决方案3】:

    cppreference.com 说:

    在构造函数初始化器中临时绑定到引用成员 list 只会持续到构造函数退出,而不是只要 对象存在。

    http://en.cppreference.com/w/cpp/language/reference_initialization

    【讨论】:

    • 谢谢,比起标准,我更喜欢 cppreference 的措辞。然而,在 C++14 之前有一条注释说,我用 gcc 标志 -std=c++14 编译了我的代码。你知道有什么不同吗?
    • 欢迎您!维基百科说 C++14 是 C++ ISO 标准最新版本的非正式名称。 [en.wikipedia.org/wiki/C%2B%2B14]我猜这意味着我们正在谈论的规则将在下一个正式标准中改变或者很可能会改变。但我不确定。
    【解决方案4】:

    生命周期只延长到B 的编译器生成器构造函数的末尾。当构造函数返回时,为保存“def”而创建的临时字符串将被销毁,留下一个悬空引用。

    【讨论】:

    • 为什么会这样?引用 s 不会超出范围,并且与结构具有相同的生命周期。
    • 因为编译器如何处理内联初始化器。将生成一个构造函数来进行初始化,这就是具有临时生命周期的范围。
    猜你喜欢
    • 2015-05-03
    • 2015-07-31
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    相关资源
    最近更新 更多