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