我试图了解编译器的默认构造函数是如何工作的。我做了这个例子:
#include <iostream>
class Base {
public:
int number;
};
class Test1 : public Base {
};
class Test2 {
public:
Base base;
};
int main() {
Test1 test1;
Test2 test2;
std::cout<<test1.number<<std::endl;
std::cout<<test2.base.number<<std::endl;
}
此测试程序的输出为test1
0
,test2
为未初始化(随机)数字。现在我的问题是:为什么在第一种情况下(test1
)编译器的默认构造函数将number
初始化为0
,但对于test2
,它不会导致{{1}} ?
编辑:根据答案,两者都会产生未定义的行为。那么,在这个程序中,编译器的默认构造函数是做什么的?
答案 0 :(得分:5)
根据8.5 / 12,未初始化对象的值为 indeterminate :
如果没有为对象指定初始值设定项,则默认初始化该对象。当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值,并且如果没有对该对象执行初始化,则该对象保留不确定的值,直到该值被替换(5.17)。
不幸的是,根据§8.5/ 7,int
属于“非默认初始化类型”类别:
默认初始化T类型的对象意味着:
- 如果T是(可能是cv限定的)类类型(第9节),则调用T的默认构造函数(12.1)(如果T没有默认构造函数或重载解析(13.3),则初始化是错误的)导致歧义或在初始化的上下文中删除或无法访问的函数中;;
- 如果T是数组类型,则每个元素都是默认初始化的;
- 否则,不执行初始化。
答案 1 :(得分:3)
实际上在这两种情况下number
都是非默认初始化的,这意味着它的值可以是任何值。碰巧test1输出0而不是一些随机数。
答案 2 :(得分:1)
就个人而言,除了最简单的情况外,我永远不会记得隐式定义的默认构造函数。所以我只在最简单的情况下依赖它。
我看了C++11 January working paper(即标准获得批准后发布的标准的编辑版本)。第12.1节第6段(p.243)声明,&#34;隐式定义的默认构造函数执行类的初始化集合,该集合将由用户编写的该类的默认构造函数执行,没有ctor-initializer和空复合语句。&#34;
如果我理解&#34; ctor-initializer&#34;和&#34;复合语句&#34;正确地说,您隐式定义的构造函数是:
Test1::Test1() {}
Test2::Test2() {}
Base::Base() {}
因此,在Test1
和Test2
中,Base::number
永远不会被初始化(Base
位于Test2
,但是Base
&# 39;隐式构造函数不初始化number
)。
至少,标准并不要求初始化Base::number
。编译器可以自由定义标准没有定义的内容。您看到0
这一事实并不意味着该操作是根据标准定义的,它只是意味着您的编译器在这种特殊情况下将事情归零。