理解隐式声明的默认构造函数

时间:2014-04-01 19:22:01

标签: c++ default-constructor

我试图了解编译器的默认构造函数是如何工作的。我做了这个例子:

#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 0test2为未初始化(随机)数字。现在我的问题是:为什么在第一种情况下(test1)编译器的默认构造函数将number初始化为0,但对于test2,它不会导致{{1}} ?

编辑:根据答案,两者都会产生未定义的行为。那么,在这个程序中,编译器的默认构造函数是做什么的?

3 个答案:

答案 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() {}

因此,在Test1Test2中,Base::number永远不会被初始化(Base位于Test2,但是Base&# 39;隐式构造函数不初始化number)。

至少,标准并不要求初始化Base::number。编译器可以自由定义标准没有定义的内容。您看到0这一事实并不意味着该操作是根据标准定义的,它只是意味着您的编译器在这种特殊情况下将事情归零。