C++ 能否将引用绑定到未初始化的成员?

C++ 能否将引用绑定到未初始化的成员?,c++,reference,C++,Reference,简短的问题,以下是可以的: 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的

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

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的指针。这里我们用new int初始化指针p。内容不被读取

同样地

 int & r = *p; //or *new int
这里我们用*p初始化引用r。内容未被阅读


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

我认为这不会调用未定义的行为

我不认为这个案例与此有任何不同:

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

同样地

 int & r = *p; //or *new int
这里我们用*p初始化引用r。内容未被阅读


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

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

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

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

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

例如,下面的代码非常好:

int *p = NULL;
int &r = *p;
这是空引用。没什么特别的


这是我的2美分。

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

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

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

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

例如,下面的代码非常好:

int *p = NULL;
int &r = *p;
这是空引用。没什么特别的


这是我的2美分。

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

指称的目的是指某物。唯一的先决条件是某种物质存在。无论它的状态定义是否明确,都是另一回事

引用的初始化不是UB。在它引用的内容被赋予一个值之前,它可以被使用,但这并不比使用初始化变量时得到的少

不同的是X:X*这个{}

在这里,您将给函数x构造函数一个指向尚未完全构造的对象的指针。这是危险的,因为一般来说,您不知道该函数将如何处理该指针,也不知道它是否期望该指针有缺陷。也许它只是为了以后的使用而储存,因此没有问题,也许它尊重它访问。。。未经改造的成员! 这是一个编译器至少应该警告的事情


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

引用和变量是不同的东西,它们都有自己的初始化

指称的目的是指某物。唯一的先决条件是某种物质存在。无论它的状态定义是否明确,都是另一回事

引用的初始化不是UB。在它引用的内容被赋予一个值之前,它可以被使用,但这并不比使用初始化变量时得到的少

不同的是X:X*这个{}

在这里,您将给函数x构造函数一个指向尚未完全构造的对象的指针。这个我 这很危险,因为一般来说,您不知道该函数将如何处理该指针,也不知道它是否期望它有缺陷。也许它只是为了以后的使用而储存,因此没有问题,也许它尊重它访问。。。未经改造的成员! 这是一个编译器至少应该警告的事情


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

Q:你试过之后发生了什么事?@paulsm4:为什么这很重要?他问这是否是未定义的行为。即使未定义,该效果仍然可以在特定编译器上工作。颠倒结构中两个成员的顺序肯定是可以的,因为它保证y首先初始化。。。只有当A是非POD类时才是这样。问:当你尝试它时发生了什么事?@paulsm4:为什么这很重要?他问这是否是未定义的行为。即使未定义,该效果仍然可以在特定编译器上工作。颠倒结构中两个成员的顺序肯定是可以的,因为它保证y首先初始化。。。只有当一个类是非POD类时,这才是正确的。这两个类是相似的,即使谈论y或*这个-它们都不是完全构造的。实际上,你所说的构造是什么意思?初始化?@LuchianGrigore:在这种特殊情况下,这两件事是一致的。但总的来说,他们没有。想象一个有许多成员的结构。当调用第三个或第三个时,第四个不被构造。通过将*this传递给第三个变量,您可以使用*this访问第四个memebr。这可以是UB,因为可能是,但不要期望它未初始化。或者它可以在第四个memebr的成员中指定一些值。。。这一点很快就会被第四个ctor所消除。在你的情况下,这是不可能发生的。构造一个引用不使用被引用的,但是*这个,在{必须被认为仍然是未定义的。这两个是相似的,即使谈论y或*这个-它们都不是完全构造的。实际上,你所说的构造是什么意思?初始化?@LuchianGrigore:在这种特殊情况下,这两个东西是一致的。但一般来说,它们不是。想象一个有许多成员的结构。当这个向量或-比方说-第三个被调用,第四个没有构造。通过将*这个传递给第三个,你可以让第三个的ctor使用*这个访问第四个memebr。这可以是UB,因为可能是,但不要期望它未初始化。或者它可以在第四个memebr的成员中分配一些值…这将很快被第四个ctor清除。这是一些在您的情况下,如果引用不使用引用,那么在{必须被认为仍然是未定义的。对于那些想要关键字的人来说:取消引用会导致左值。未初始化变量的UB来自左值到右值的转换,这是“读取变量”的技术部分。因为我们只得到对未初始化对象的左值引用,这没关系。一旦有什么事情导致hat转换为右值,即需要初始化某物。@GManNickG:感谢词汇表和额外的解释。对于那些想要关键字的人:取消引用会导致左值。未初始化变量的UB来自左值到右值的转换,这是“读取va”的技术部分“变量”。因为我们只得到一个对未初始化对象的左值引用,这没关系。一旦某个东西导致转换为右值,则需要初始化该东西。@GManNickG:谢谢您提供的词汇表和额外的解释。