C++ 默认初始化与零初始化

C++ 默认初始化与零初始化,c++,initialization,default,zero,C++,Initialization,Default,Zero,我无法理解gcc 4.8.1或Visual Studio 2015在默认初始化和值初始化方面的行为 我自己试图理解它们之间的差异,可能遇到编译器错误,这对我没有帮助 我的问题是:有人能解释这种行为吗?最好告诉我应该发生什么。 我有两门课: class Foo{ int _bar; public: void printBar(){ cout << _bar << endl; } }; class bar{ int ent; public:

我无法理解gcc 4.8.1或Visual Studio 2015在默认初始化和值初始化方面的行为

我自己试图理解它们之间的差异,可能遇到编译器错误,这对我没有帮助

我的问题是:有人能解释这种行为吗?最好告诉我应该发生什么。

我有两门课:

class Foo{
    int _bar;
public:
    void printBar(){ cout << _bar << endl; }
};

class bar{
    int ent;
public:
    int getEnt(){return ent;}
};
class-Foo{
国际酒吧;
公众:
void printBar(){coutn3376引号

8.5/11

如果没有为对象指定初始值设定项,则该对象为 默认初始化;如果未执行初始化,则具有 自动或动态存储持续时间的值不确定。[注意: 具有静态或线程存储持续时间的对象初始化为零, 见3.6.2.-结束注释]

8.5/6

默认初始化T类型的对象意味着:如果T是(可能是 cv合格)类类型(第9条),T的默认构造函数为 调用(如果T没有可访问的 默认构造函数)

8.5/10

初始值设定项为空括号集的对象,即(), 应初始化该值

8.5/7

初始化T类型对象的值意味着:

否则,对象初始化为零

8.5/5

零初始化类型为T的对象或引用意味着:如果T是 (可能是cv限定的)非联合类类型,每个非静态数据 成员和每个基类子对象都是零初始化和填充的 初始化为零位

因此,在您的情况下,没有静态存储持续时间变量,也没有线程局部变量,因此对象
foo
b
将被默认初始化,这意味着将调用该构造函数。默认构造函数(非用户定义)不会初始化成员,in成员将是任意垃圾,此任意垃圾可能为0(感谢Jarod42在注释中的这一点)。
Foo().printBar();
应该打印0,因为对象初始化为零。

逻辑非常简单:

  • 类的默认初始化只是默认初始化所有成员
  • 内置类型的默认初始化使成员未初始化
  • 访问未初始化的对象会产生错误
  • 未定义的行为可以做它想做的任何事情
  • 两个编译器都提供了“正确”的结果。请注意,导致发出的结果也是正确的
  • 此默认值初始化
    foo
    ,并且由于
    foo
    的默认构造函数很小,它实际上根本不会初始化它,因此
    foo.\u bar
    可以保存任何值(包括0)


    此值初始化临时对象,在普通默认构造函数的情况下,这意味着零初始化,因此
    Foo()。\u bar
    等于0。

    对于这样没有用户定义构造函数的类,默认初始化不起任何作用,给每个普通成员留下一个不确定的值

    值初始化将为零初始化每个成员

    在第一种情况下,您正在打印:

    • 初始化的默认值的不确定值
      Foo-Foo;
    • 初始化的值的零值
      Foo()
    • 默认初始化的
      条b的不确定值;
    第三个值恰好为零;可能是因为它重用了初始化为
    Foo
    的临时值的存储

    在第二种情况下,您正在打印两个默认初始化对象的不确定值。巧合的是,它们在一种情况下为零值,而在另一种情况下为零


    这两个程序都有未定义的行为,因为它们使用未初始化的值。

    如果有人感兴趣,我开始研究这个问题,以回答:这个问题不一样吗?@AntonSavin我真的只是想知道编译器在初始化时应该做些什么。我不认为这是同一个问题。对于调试构建,通常需要填充用于帮助检测未初始化的值…其他字节用于帮助检测其他与内存相关的问题(如已释放的内存)。并且任意垃圾可能是
    0
    。值得一提的是
    Foo().printBar();
    必须打印0(至少在程序中有其他UB的情况下,
    必须自己打印)@Jarod42这实际上是一个非常好的评论。我没有考虑到默认初始化可能会产生一个0结果。嗯……一定有办法处理这个问题,这样我才能真正看到发生了什么。如果这有点迂腐,很抱歉,但对于
    struct String{std::String str;}这样的类,您肯定不希望零初始化;
    只是因为它没有用户提供的默认构造函数。
    int main()
    {
        Foo foo;
    
        foo.printBar();
        Foo().printBar();
    
        bar b;
    
        cout << b.getEnt() << endl;
    
        return 0;
    }
    
    int main()
    {
        Foo foo;
    
        foo.printBar();
    
        bar b;
    
        cout << b.getEnt() << endl;
    
        return 0;
    }
    
    Foo foo;
    
    Foo()