1. default constructors 在需要的时候被编译器产生出来。 Global objects的内存保证会在程序激活的时候被清为0.Local objects配置于程序的堆栈中,heap objects配置于自由空间中,都不一定会被清为0,它们的
内容是内存上次被使用后的遗迹。
2. 编译器生成nontrivial constructor
(1) 带有Default Constructor的Member Class Object
如果一个class没有任何constructor,但它内含一个member object,而后者有default constructor,那么这个class的implicit default constructor就是nontrivial,编译器需要为此class合成一个default constructor.
如果有多个class member objects要求constructor初始化操作,编译器将为每一个constructor安插程序代码,以member声明次序调用每一个member所关联的default constructors。
(2) 带有Default Constructor的Base Class
如果一个没有任何constructors的class派生自一个带有default constructor的base class,那么这个derived class的default constructor会被视为nontrivial,因此需要被合成出来。它将调用上一层base classes的
default constructor。
(3) 带有一个virtual function的class
class声明或继承一个virtual function;
1 class Widget { 2 public: 3 virtual void flip() = 0; 4 }; 5 6 void flip(const Widget& widget) { 7 widget.flip(); 8 } 9 10 void foo() { 11 Bell b; 12 Whistle w; 13 14 flip(b); 15 flip(w); 16 }
下面两个操作会在编译器间发生:
一个virtual function table会被编译器产生出来,内放class的virtual functions地址。
在每一个class object中,一个额外的pointer member会被编译器合成出来,内含相关的class vtbl的地址。
class派生自一个继承串链,其中有一个或更多的virtual base classes.
必须使virtual base class在其每一个derived class object中的位置,能够于执行期准备妥当。对于class所定义的每一个constructor,编译器安插那些“允许每一个virtual base class的执行期存取操作”的码,如果class没有声明任何constructors,编译器必须为它合成一个default constructor。
Copy Constructor 的建构操作
有三种情况,会以一个object的内容作为另一个class object的初值。最明显的一种情况是对一个object做明确的初始化操作:
class X {};
X x;
另两种情况是当object被当作参数交给某个函数时,如:
1 extern void foo(X x); 2 3 void bar() { 4 X xx; 5 foo(xx); // 以x作为foo()第一个参数的初值 6 }
以及当函数传回一个class object时,如:
X foo_bar() { X xx; return xx; }
Bitwise Copy Semantics(位逐次拷贝)
只有nontrivial的实体才会被合成于程序之中,决定一个copy constructor是否为trivial的标准在于class是否展现出所谓的bitwise copy semantics。
什么时候一个class不展现出 bitwise copy semantics:
(1)当class内含一个member object而后者的class声明有一个copy constructor时;
(2)当class继承自一个base class而后者存在有一个copy constructor时;
(3)当class声明了一个或多个virtual functions时;
(4)当class派生自一个继承串链,其中有一个或多个virtual base classes时。
前两种情况中,编译器必须将member或base class的copy constructors调用操作安插到被合成的copy constructor中。
对于3,合成出来的copy constructor会明确设定object的vptr指向其类的virtual table,而不是直接从右手边的class object中将其vptr现值拷贝过来。
对于4,一个class object如果以另一个object为初值,而后者有一个virtual base class subobject,那么也会使bitwise copy semantics失效。
每个编译器对于虚拟继承的支持承诺,都表示必须让derived class object中的virtual base class subobject位置在执行期就准备妥当。
成员初始化列表
一下情况必须使用成员初始化列表:
(1)当初始化一个reference member时;
(2)当初始化一个const member时;
(3)当调用一个base class的constructor,而它拥有一组参数时;
(4)当调用一个member class的constructor,而它拥有一组参数时。
编译器会操作initialization list,以适当次序在constructor之内安插初始化操作,并且在任何explicit user code之前。list中的项目次序是由class中的members声明次序决定,不是由initialization list中的排列次序决定。