非POD类型的零初始化

3
为什么在下面的非POD类中,x被初始化为零?
class test {
public:
    void print() {
        cout << x << endl;
    }
private:
    int x;
};

int main(int argc, char** argv)
{
    test * tst = new test();
    tst->print();
    cout << is_pod<test>::value << endl;
}

tst->print()和is_pod()都返回0。


调试版或发布版? - Michael Chourdakis
当我打印虚函数时,x是一个随机数,但在上面发布的代码中它总是零。 - michalt38
2
未初始化的变量具有不确定的值。不确定并不意味着“随机”或“垃圾”(尽管可能是),只是该值是未知的。使用不确定的值会导致未定义的行为。然而,在这种情况下,x 没有被初始化。 - Some programmer dude
1
标准并不强制要求非 POD(平凡标量类型)的成员使用随机值进行初始化。编译器可能仍然根据大量因素对内存进行零初始化。 - UmNyobe
这不是因为调试吗? - Yunus Temurlenk
显示剩余2条评论
1个回答

7

这是没有用户提供构造函数的类value-initialization的结果。

在这种情况下,T()new T()首先执行零初始化:

如果T是具有既不是用户提供的也不是删除的默认构造函数的类类型(即可能是具有隐式定义或默认定义的默认构造函数的类),则对象将进行零初始化,然后如果它具有非平凡的默认构造函数,则进行默认初始化;

零初始化的影响如下:

如果T是一个非联合类类型,则所有基类和非静态数据成员都将被零初始化,并且所有填充都将被初始化为零位。构造函数(如果有)将被忽略。

如果 T 是标量类型,对象的初始值是明确转换为 T 的整数常量零。

1
错误。这仍然是默认初始化的。引用如此说明。 - UmNyobe
4
如果一个对象具有非平凡默认构造函数,则它将被默认初始化。由于成员已经被零初始化,所以默认初始化是否重要(因为它不会删除或取消之前的初始化)? - Some programmer dude
2
@UmNyobe 创建的 test 对象是通过 new test() 进行 _值初始化_,这会对其成员进行 _零初始化_。相应的标准段落为dcl.init/8.2 - Daniel Langr
3
@KamilCuk 但是初始化器并不缺失。它以空的初始化器()的形式存在。例如,在 cppreference 上明确指出了这一点。在不提供初始化器和提供一个空的初始化器之间存在差异。(这就是为什么你总是要提供一个初始化器而不用担心这个怪癖的原因。) - underscore_d
1
@michalt38,在一般情况下 - 是的。但在这种特殊情况下,隐式定义的默认构造函数是微不足道的(不作任何操作),因此它不会被调用。 - Evg
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接