提问人:Luchian Grigore 提问时间:7/5/2012 更新时间:7/5/2012 访问量:277
是否可以将引用绑定到未初始化的成员?
Can you bind a reference to an uninitialized member?
问:
简短的问题,以下可以吗:
struct X
{
A& x;
A y;
X() : x(y) {}
};
颠倒结构中两个成员的顺序肯定是可以的,因为它保证首先初始化,但这是否有效或调用 UB?y
此外,以下情况是否正常:
struct X
{
X& x;
X() : x(*this) {}
};
?
答:
我不认为这会引发未定义的行为。
我看不出这种情况与此有什么不同:
int *p = new int;
表达式是指向未初始化的 int 的指针。这里我们用 初始化指针。不读取内容。new int
p
new int
同样地
int & r = *p; //or *new int
在这里,我们使用 初始化引用。未读取内容r
*p
在这两种情况下,都不会读取内容。读取未初始化的变量会调用未定义的行为。在这两种情况下,未初始化的是内容,而不是地址,我们没有读取内容。
评论
我认为将这个问题分成其他几点是有意义的:
- 这在语法上是否正确,这是否只允许一种实现?
- 此代码是否会导致崩溃和高级问题?
- 编译器应该处理第二个问题吗?
我会回答:Y,Y,Y/N。
我在上面的代码示例中没有看到歧义。语法正确的代码会以数百万种方式损坏内存、崩溃等。这是另一个例子。
编译器可能会发出警告,因为上面的例子是显而易见的。在具有大量间接、重新定义等的实际场景中,编译器可能会感到困惑。我不会责怪它太过分。算法分析是另一个工具的工作,而不是编译器。
例如,下面的代码完全没问题:
int *p = NULL;
int &r = *p;
这是 NULL 引用。没什么特别的。
这些是我的 2 美分。
引用和变量是截然不同的东西,每个都有自己的“初始化”。
引用的目的是引用某物
。唯一的先决条件是物理存在。无论它的状态是否定义明确,都是另一回事。something
引用的初始化不是 UB。它可以是UB的使用,在它所引用的东西被赋予一个值之前,但这不多也不少于你在使用初始化变量时得到的。
不同的东西是X() :x(*this) {}
在这里,你给一个函数(x 构造函数)一个指向尚未完全构造的东西的指针。这是“危险的”,因为一般来说,你不知道该函数将如何处理该指针,以及它是否期望它以某种方式“有缺陷”。也许它只是“存储以备后用”(因此没有问题)可能是尊重它访问......未重建的成员! 这是编译器至少应该警告的事情。
当然,在这种特殊情况下(您只是初始化一个引用),这不会成为问题,因为“引用构造器”不会访问引用的对象。但总的来说不是一个好主意。
评论
y
*this
{
评论
A