简短的问题,以下是好的:
struct X
{
A& x;
A y;
X() : x(y) {}
};
反转结构中两个成员的顺序绝对可以,因为它保证y
首先被初始化,但这是否有效或者调用UB?
Moreso,以下是可以的:
struct X
{
X& x;
X() : x(*this) {}
};
答案 0 :(得分:3)
我认为这不会引发未定义的行为。
我没有看到这种情况与此有任何不同:
int *p = new int;
表达式new int
是指向未初始化 int的指针。这里我们用p
初始化指针 new int
。 内容未被阅读。
类似地,
int & r = *p; //or *new int
我们正在使用r
初始化引用 *p
。 内容未读取
在这两种情况下,都不会读取内容。 读取未初始化的变量会调用未定义的行为。在这两种情况下,内容都是未初始化的,而不是地址,我们不是正在阅读内容。
答案 1 :(得分:1)
引用和变量是不同的东西,每个都有自己的“初始化”。
参考的目的是引用something
。唯一的先决条件是something
实际存在。无论其状态是否明确,都是另一个故事。
引用的初始化不是UB。它可以是UB的使用,在它被引用的值之前,但这不再是你使用初始化变量时得到的。
不同的是X() :x(*this) {}
这里给出一个函数(x构造函数)指向尚未完全构造的东西的指针。这是“危险的”,因为 - 一般情况下 - 你不知道该函数将对该指针做什么,以及它是否期望它以某种方式“被打开”。可能它只是“存储它以供以后使用”(因此没有问题)可能是它尊重它访问...未经重建的成员! 这是编译器至少应该警告的东西。
当然,在这种特殊情况下(您只是初始化一个引用),它不会成为问题,因为“引用构造函数”不会访问引用的对象。但总的来说不是一个好主意。
答案 2 :(得分:0)
我认为将此问题分成几个其他问题是有意义的:
我会回答:Y,Y,Y / N.
我没有看到上面代码示例中的含糊不清。有数百万种语法正确的代码会破坏内存,崩溃等等。这是另一个例子。
编译器可能会发出警告,因为上面的示例很明显。在具有大量间接,重新定义等的真实场景中,编译器可能会感到困惑。我不会太难以责备它。算法分析是另一个工具的工作,而不是编译器。
例如,下面的代码非常好:
int *p = NULL;
int &r = *p;
这是NULL引用。没什么特别的。
这是我的2美分。