C++ 默认初始化与零初始化
我无法理解gcc 4.8.1或Visual Studio 2015在默认初始化和值初始化方面的行为 我自己试图理解它们之间的差异,可能遇到编译器错误,这对我没有帮助 我的问题是:有人能解释这种行为吗?最好告诉我应该发生什么。 我有两门课: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:
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()