- 明确什么时候是程序需要默认构造函数,什么时候是编译器需要默认构造函数。
- 对于
class X
,如果没有程序声明的构造函数,那么会有一个默认构造函数被隐式声明出来。它将是一个trivial constructor
,是一个什么都不做的构造函数。 - 特殊地,
Global objects
的内存保证会在程序启用的时候被清为0;Local objects
配置于程序的堆栈中,堆对象配置于自由空间中,都不一定会被清为0,它们的内容将是内存上次被使用后的遗留。
-
如果一个
class
没有任何constructor
,但它内含一个member object
,而后者有default constructor
,那么这个class
的implicit default constructor
就是nontrivial
,编译器需要为该class
合成出一个default constructor
。编译器会扩张已存在的constructors
,在其中安插一些代码,使得user code
被执行前,先调用必要的default constructors
。class Foo { public: Foo(); }; class Bar { public: Foo foo_; char *str_; }
- 这里
Bar
的隐式构造函数会自动调用Foo
的默认构造函数,但它并不产生任何代码来初始化Bar::str_
。初始化Bar::foo_
是编译器的责任,初始化Bar::str_
则是程序员的责任。 - 如果
Bar
包含多个member class object
,那么会以member objects
在class
中的声明顺序来依次调用。
- 这里
-
再次注意,被合成的
default constructor
只满足编译器的需要,而不是程序的需要。
- 同样,如果一个没有任何
constructors
的class
派生自一个带有default constructor
的base class
,那么这个派生类的default constructor
会被视为nontrivial
,并因此需要被合成出来。 - 将会根据声明的继承顺序,依次调用其
default constructor
。
- 有两种情况:
class
声明或继承一个virtual function
。class
派生自一个继承串链,其中有一个或多个virtual base classes
。
- 编译器也会合成出
default constructor
,以便正确的初始化每一个class object
的虚函数指针。
- 不同编译器实现之间存在较大差异。
- 有三种情况会调用拷贝构造函数:
- 对一个对象做显式的初始化操作。
- 当对象被当作参数交给传递给某个函数时。
- 当函数返回一个类对象时。
- 语言允许编译器有大量的自由发挥空间,用来提升效率。例如:函数值传递返回一个类对象,对其进行优化处理。