我们都知道这样的事情在 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
版本因为编译看到了所有const
s 并直接打印出 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(使用前将#替换为@)