2

简短的问题,以下是否可以:

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

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

此外,以下是否可以:

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

?

4

3 回答 3

3

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

我认为这种情况与此没有什么不同:

 int *p = new int;

该表达式new int是一个指向未初始化的int 的指针。这里我们用初始化指针 。内容读。pnew int

相似地,

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

这里我们用初始化引用 。内容r*p

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

于 2012-07-05T06:14:12.057 回答
1

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

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

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

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

在这里,您向函数( x 构造函数)提供了一个指向尚未完全构造的东西的指针。这是“危险的”,因为 - 通常 - 你不知道该函数将对该指针做什么,以及它是否期望它以某种方式“有缺陷”。可能只是“存储它以备后用”(因此没问题)可能是它尊重它以访问......未重建的成员!这是编译器至少应该警告的事情。

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

于 2012-07-05T06:34:31.237 回答
0

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

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

我会回答:是,是,是/否。

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

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

例如下面的代码非常好:

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

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

这是我的 2 美分。

于 2012-07-05T06:24:05.380 回答