是否可以将引用绑定到未初始化的成员?

Can you bind a reference to an uninitialized member?

提问人:Luchian Grigore 提问时间:7/5/2012 更新时间:7/5/2012 访问量:277

问:

简短的问题,以下可以吗:

struct X
{
    A& x;
    A  y;
    X() : x(y) {}
};

颠倒结构中两个成员的顺序肯定是可以的,因为它保证首先初始化,但这是否有效或调用 UB?y

此外,以下情况是否正常:

struct X
{
   X& x;
   X() : x(*this) {}
};

?

C++ 参考手册

评论

0赞 paulsm4 7/5/2012
问:当你尝试它时发生了什么?
2赞 Nicol Bolas 7/5/2012
@paulsm4:为什么这很重要?他问这是否是未定义的行为。即使未定义,该效果仍然可以在特定编译器上“起作用”。
0赞 Nawaz 7/5/2012
颠倒结构中两个成员的顺序绝对是可以的,因为它保证 y 首先被初始化......只有当是非 POD 类时,这才成立。A

答:

3赞 Nawaz 7/5/2012 #1

我不认为这会引发未定义的行为。

我看不出这种情况与此有什么不同:

 int *p = new int;

表达式是指向未初始化的 int 的指针。这里我们用 初始化指针不读取内容new intpnew int

同样地

 int & r = *p; //or *new int

在这里,我们使用 初始化引用未读取内容r*p

在这两种情况下,都不会读取内容读取未初始化的变量会调用未定义的行为。在这两种情况下,未初始化的是内容,而不是地址,我们没有读取内容

评论

3赞 GManNickG 7/5/2012
对于那些想要关键字的人:取消引用会导致左值。来自未初始化变量的 UB 来自左值到右值的转换,这是“读取变量”的技术部分。因为我们只得到一个对未初始化对象的左值引用,所以没关系。一旦某些东西导致该东西转换为右值,初始化该东西的要求就会开始。
0赞 Nawaz 7/5/2012
@GManNickG:感谢您的词汇和补充解释。
0赞 Kirill Kobelev 7/5/2012 #2

我认为将这个问题分成其他几点是有意义的:

  1. 这在语法上是否正确,这是否只允许一种实现?
  2. 此代码是否会导致崩溃和高级问题?
  3. 编译器应该处理第二个问题吗?

我会回答:Y,Y,Y/N。

我在上面的代码示例中没有看到歧义。语法正确的代码会以数百万种方式损坏内存、崩溃等。这是另一个例子。

编译器可能会发出警告,因为上面的例子是显而易见的。在具有大量间接、重新定义等的实际场景中,编译器可能会感到困惑。我不会责怪它太过分。算法分析是另一个工具的工作,而不是编译器。

例如,下面的代码完全没问题:

int *p = NULL;
int &r = *p;

这是 NULL 引用。没什么特别的。

这些是我的 2 美分。

1赞 Emilio Garavaglia 7/5/2012 #3

引用和变量是截然不同的东西,每个都有自己的“初始化”。

引用的目的是引用某物。唯一的先决条件是物理存在。无论它的状态是否定义明确,都是另一回事。something

引用的初始化不是 UB。它可以是UB的使用,在它所引用的东西被赋予一个值之前,但这不多也不少于你在使用初始化变量时得到的。

不同的东西是X() :x(*this) {}

在这里,你给一个函数(x 构造函数)一个指向尚未完全构造的东西的指针。这是“危险的”,因为一般来说,你不知道该函数将如何处理该指针,以及它是否期望它以某种方式“有缺陷”。也许它只是“存储以备后用”(因此没有问题)可能是尊重它访问......未重建的成员! 这是编译器至少应该警告的事情。

当然,在这种特殊情况下(您只是初始化一个引用),这不会成为问题,因为“引用构造器”不会访问引用的对象。但总的来说不是一个好主意。

评论

0赞 Luchian Grigore 7/5/2012
两者是相似的,即使谈论或 - 它们都没有完全构建。实际上,你说的构造是什么意思?初始 化?y*this
0赞 Emilio Garavaglia 7/5/2012
@LuchianGrigore:在这种特殊情况下,这两件事是重合的。但总的来说,他们没有。想象一个包含许多成员的结构。当 ctor 或 - 比方说 - 调用第三个时,第四个不会被构造。通过将 *this 传递给第三个,您可以让第三个的 ctor 使用 *this 访问 fouth memebr。这可以是 UB,因为它可能不希望它未初始化。或者它可以在第 4 个 memebr 的成员中分配一些值......这将很快被第 4 CTOR 消灭。
0赞 Emilio Garavaglia 7/5/2012
在你的情况下,这是永远不会发生的事情(构造引用不会“使用”引用),但是*这个,在必须考虑之前仍然未定义。{