为什么这个简单的任务没有定义行为

Why is this simple assignment undefined behaviour?

本文关键字:定义 任务 简单 为什么      更新时间:2023-10-16

我刷新了对值初始化与默认初始化的理解,发现了以下内容:

struct C {
    int x;
    int y;
    C () { }
};
int main () {
    C c = C ();
}

显然这是UB因为

在C()的情况下,有一个构造函数能够初始化x和y成员,因此不会进行初始化。因此,试图将C()复制到C会导致未定义的行为。

我想我明白为什么,但我不确定。有人能详细说明吗?

这是否意味着这里也是UB?

int x; x = x;

顺便说一句,关于值初始化,以下内容是否保证为零?

int x = int ();

您的第一个示例有未定义的行为,因为默认的编译器生成的复制构造函数将执行成员复制,int s可能具有补漏白值,并且读取补漏白值来复制它可能会导致程序崩溃。

在实践中,我无法想象这会真的崩溃;编译器几乎肯定会优化复制,即使没有可能会使用一些特殊的逐位复制检查补漏白值。(在C++中,您保证能够复制字节。)

对于第二种情况,同样是未定义的行为。尽管在这种情况下,你有赋值结构而不是复制结构,编译器是不太可能对其进行优化。(你的第一个作业中没有作业例如,仅复制构造。)

对于第三个,是的。带有空括号(且没有用户定义的默认初始值设定项覆盖它)首先执行零初始化(与具有静态生存期的变量完全一样)。

我不认为这实际上是undefined behavior,尽管c中的值有unspecified values。也就是说,只要你最终没有使用这些未指定的值,程序的行为就被很好地定义了。如果您使用它们,例如在条件中或打印它们,则不会定义结果。然而,我不认为这个程序被允许做任何奇怪的事情。

关于在内置类型上使用默认构造函数,这可以保证生成类型的零值,即整数为0,浮点类型为0.0等。这也扩展到没有构造函数的类型的成员。一旦有了构造函数,你就需要在没有构造函数的情况下构建你的成员。

否。将会发生的是,大多数编译器都会优化变量out的设置,但那些不这样做的编译器根本不会改变x的值。这与以下代码相同:

int x = 0;
x = 0;

这并不是说第二行不会执行,它只是不会做任何事情。