首页 > 代码库 > 编译器会自动生成default constructor,这是真的吗?
编译器会自动生成default constructor,这是真的吗?
编译器会自动生成default constructor,这是真的吗?
相信很多人的回答都是“是的吧“。Okay,是不是真的先不提了,先来看一个例子看看下面的代码能否编译通过,如果编译通过,能运行吗?如果不能运行,在哪出错?
class foo { public: int val; foo *pNext; }; void Test1(){ foo f; if (f.val || f.pNext ){ cout << "in if" << endl; } } int main(){ Test1(); return 0; }事实上,上述代码可以编译通过,但是不能够运行。在if判断那里出错了,因为f没有初始化。这时候有些人就开始有凝问了,f 不是由编译器产生类foo的默认构造函数来初始化吗?好,我们先来看看编译器什么时候编译器产生默认构造函数?
C++手册中说" 默认构造函数会在需要的时候被编译器产生出来”关键是需要的时候。上面的例子也是需要啊,咋就没有产生默认构造函数喃?原因是,需要的时候这个有两层意思:一个是程序的需要,另一个是编译器的需要。程序如果需要,那就是程序员的责任,上面的例子就是程序的需要,所以就是设计该类的人负责设计初始化代码。
那什么时候才会合成出一个默认构造函数?答案是当编译器需要的时候,并且并合成出来的构造函数只执行编译器所需的动作。
C++ standard中说明“对于class X,如果没有任何user-defined constructor,那么会有一个default constructor被隐式(implicitly)声明出来,一个被隐式声明出来的default constructor将是一个trivial(没啥用的)constructor。
nontrivial default constructor就是编译器需要的默认构造函数。下面主要看4种生成nontrivial default constructor的情况。
一、”带有Default Constructor“的Member Class Object
如果一个class没有任何constructor,但它内含一个member object,而后者有default constructor,那么这个class的implicit default constructor就是”nontrivial“,编译器需要为该class合成一个default constructor。不过这个合成操作只有在constructor真正需要被调用的时候才会发生。
举个例子,在下面的程序中,编译器为class B 合成一个default constructor:
class A{ public: A(); A(int x){}..... }; class B : { public : A a; char *str }; void Test(){ B b;}
被合成的B default constructor内含必要的代码,能够调用class A的default constructor来处理member object B::a.但是它并不产生代码来初始化B::str。将B::a初始化是编译器的责任,将B::str初始化则是程序员的责任。
上述程序还不能运行,因为B::str没有初始化,所以程序员必须提高默认构造函数初始化str。
如果一个class X内含有一个或一个以上的member class object,那么class A的每一个constructor必须调用每一个member class的default constructor。并且如果有多个class member objects都要求constructor初始化操作,编译器将按照以”member objects在class中的声明顺序“来调用各个constructors。例如,假设有三个类:
class A{ public: A(); ....}; class B{ public: B(); ...}; class C{ public: C(); ...};
以及一个class D:
class D{ public: A a; B b; C c; ... private: int number; };
如果D没有定义default constructor,就会有一个nontrivial constructor被合成出来,依序调用A,B,C的default constructor。然而如果D定义了下面的default constructor:
D::D:B(360){number=90;}
编译器就会扩张上述构造函数执行操作为 D::D:B(360){A();B(360);C();number=90;}
二、"带有Default Constructor"的Base Class
如果一个没有任何constructors的class派生自一个”带有default constructor“的base class,那么这个derived class的default constructor会被视为nontrivial,并因此需要被合并出来。它将调用上一层base classes的default constructor。
如果设计者提供多个constructor,但其中都没有default constructor喃?编译器会扩张现有的每一个constructor,将”用以调用所有必要之default constructors“的程序代码加进去。它不会合成一个新的default constructor,因为其他”由user提供的constructors”存在的缘故。如果同时存在“带有default constructor”的member class object,在所有base class constructor都被调用之后,那些default constructor也都会被调用。
三、”带有一个Virtual Function“的class
这种情况下,编译器会生成默认构造函数,并且执行下面两个步骤,
1. 一个virtual function table(vtbl) 会被编译器产生出来,内放class的virtual functions的地址。
2. 在每一个class object中,一个额外的pointer member会被编译器产生出来,内含相关之class vtbl的地址。
四、“带有一个Virtual Base Class”的class
Virtual Base Class的实现法在不同的编译器之间有极大的差异。然而,每一种现实法的共同点在于必须使virtual base class在其每一个derived class object中的位置能够在执行器准备妥当。(深入探索C++对象模型)
总结:
被合成出来的implicit nontrivial default constructors只能满足编译器的需要。它之所以能够完成任务,是借着“调用member object或者base class的default constructor”或是“为每一个object初始化其virtual function机制或virtual base class机制”而完成额。至于没有存在这4种情况而又没有声明任何constructor的classes,其拥有的是implicit trivial default constructors,它们实际上并不会被合成出来。
在合成的default constructor中,只有base class subobjects和member class objects会被初始化。所有其他的nonstatic data member(如整数、整数指针、整数数组等)都不会被初始化。
C++新手一般有两个常见的误解:
1. 任何class如果没有定义default constructor,就会被合成出来一个。
2. 编译器合成出来的default constructor会显示设定“class内每一个data member的默认值”
如果你觉得本篇对你有收获,请帮顶。
另外,我本人开通了微信公众号--分享技术之美,我会不定期的分享一些我学习的东西.
另外,我本人开通了微信公众号--分享技术之美,我会不定期的分享一些我学习的东西.
你可以搜索公众号:swalge 或者扫描下方二维码关注我
(转载文章请注明出处: http://blog.csdn.net/swagle/article/details/24453257 )
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。