12

我正在刷新我对值初始化与默认初始化的理解,并遇到了这个

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 ();
4

3 回答 3

13

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

在实践中,我无法想象这真的会崩溃。编译器几乎肯定会优化复制出来,即使没有,它也可能会使用一些特殊的按位复制来复制而不检查陷阱值。(在 C++ 中,保证您能够复制字节。)

对于第二种情况,同样是未定义的行为。尽管在这种情况下,您有分配而不是复制构造,并且编译器不太可能将其优化掉。(在您的第一个示例中没有分配,只有复制构造。)

第三个,是的。带有空括号的初始化程序(并且没有用户定义的默认初始化程序来覆盖它)首先执行零初始化(与具有静态生命周期的变量完全相同)。

于 2012-02-06T16:49:51.700 回答
1

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

关于在内置类型上使用默认构造函数,这可以保证产生类型的零值,即0对于整数、0.0浮点类型等。这也扩展到没有构造函数的类型的成员。一旦有任何构造函数,您需要自己处理没有构造函数的构造成员。

于 2012-02-06T16:50:18.737 回答
-1

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

int x = 0;
x = 0;

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

于 2012-02-06T16:38:46.817 回答