对临时异常的 const 引用

2023-11-21

我们都知道这样的事情在 C++ 中是有效的:

const T &x = T();

while:

T &x = T();

is not.

In 最近的一个问题谈话导致了这条规则。 OP 发布了一些明显让人想起 UB 的代码。但我希望它的修改版本能够工作(这是修改版本):

#include <iostream>
using namespace std;

class A {
public:
    A(int k) { _k = k; };
    int get() const { return _k; };
    int _k;
};

class B {
public:
    B(const A& a) : _a(a) {}
    void b() { cout << _a.get(); }
    const A& _a;
};

B* f() {
    return new B(A(10));
}

int main() {
    f()->b();
}

这在某些机器上打印垃圾,在其他机器上打印 10 个......对我来说听起来像 UB :-)。但后来我想,好吧A基本上是一种美化int它所做的一切都是初始化并读取它。为什么不直接打电话A an int看看会发生什么:

#include <iostream>
using namespace std;

typedef int A;

class B {
public:
    B(const A& a) : _a(a) {}
    void b() { cout << _a; }
    const A& _a;
};

B* f() {
    return new B(A(10));
}

int main() {
    f()->b();
}

它打印10每次。它至少seems就像 const 引用规则适用于int版本,但不适用于班级版本。由于堆的使用,它们都是简单的 UB 吗?我只是幸运吗int版本因为编译看到了所有consts 并直接打印出 a10?我缺少规则的哪一方面?


它只是表明通过“在编译器中尝试”来分析语言行为通常不会产生任何有用的结果。由于同样的原因,您的两个示例均无效。

仅当您使用该临时文件作为 const 引用的直接初始化程序时,临时文件的生命周期才会延长 - 只有这样才会在引用和临时文件之间建立“生命周期”链接。

尝试将临时变量作为构造函数的参数传递并在构造函数内部附加 const 引用将不会建立上述链接,也不会延长临时变量的生命周期。

另外,根据 C++ 标准,如果你这样做

struct S {
  const int &r;

  S() : r(5) {
    cout << r; // OK
  }
};

临时变量的生命周期仅延长到构造函数的末尾。一旦构造函数完成,临时对象就会消失,这意味着

S s;
cout << s.r; // Invalid

是无效的。

你的实验int只是“似乎有效”,纯粹是偶然的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

对临时异常的 const 引用 的相关文章

随机推荐