- explicit:能够制止单一参数的构造函数被当作一个conversion运算符。
- 全局对象的内存保证在程序启动的时候被清为0,局部对象配置于程序的堆栈中,堆对象配置于自由空间中,都不一定会被清为0,它们的内容将是上次被使用后的遗迹。
2.1默认构造函数的构造操作
nontrivial default constructor
-
带有默认构造函数的成员类对象
- 被合成的默认构造函数只满足编译器的需要,而不是程序的需要。
- C++语言要求以member objects 在类中的声明顺序来调用各个构造函数,这些代码被安插在user code之前。
-
带有默认构造函数的基类
- 如果同时亦存在着带有默认构造函数的成员类对象,那些默认构造函数也会被调用,在所有的基类构造函数都被调用之后。
-
带有一个虚函数的类
- 类声明(或继承) 一个虚函数。
- 类派生自一个继承串链,其中有一个或更多个虚基类。
- 一个虚函数表会被编译器产生出来,内放class的虚函数地址
- 在每一个类对象中,一个额外的vptr会被编译器合成出来,内含相关的class vtbl的地址。
-
带有一个虚基类的类
- 对于类所定义的每一个构造函数,编译器会安插那些允许每一个虚基类的执行期存取操作的代码。
2.2 拷贝构造函数的构造操作
- 一个对象的内容会作为另一个类对象的初值:
- 对一个对象做显示的初始化操作
- 当对象被当作参数交给某个函数时
- 当函数返回一个类对象时。
默认成员初始化
- 当类对象以相同类的另一个对象作为初值,其内部是以所谓的默认成员初始化完成的,也就是把每一个内建的或者派生的数据成员(l例如指针或者数组)的值,从某个对象拷贝一份到另一个对象身上。
- 不过他并不会拷贝其中的成员类对象,而是以递归的方式施行成员初始化。
- 决定一个拷贝构造函数是否为重要的标准在于是否展现出按位拷贝的语义
不要位逐次拷贝
- 当类内含一个成员对象而后者的类声明有一个拷贝构造函数时。
- 当类继承一个基类而后者有一个拷贝构造函数
- 当类声明一个或者多个虚函数时
- 当类派生自一个继承串联,其中有一个或多个虚基类时。
重新设定虚表指针
- 当编译器导入一个vptr到class之中时,该类就不再展现出位逐次拷贝的语义了,现在编译器需要合成出一个拷贝构造函数以求将vptr适当的初始化。
处理虚基类的子对象
- 一个类对象如果以另一个对象作为初值,而后者有一个虚基类子对象,那么也会使位逐次拷贝失效。
总结:
- 在上面四种情况下,类不在表现位逐次拷贝的语义,而且默认拷贝构造函数如果未被声明的话,会被视为重要的,在这四种情况下,如果缺乏一个以声明的拷贝构造函数,编译器为了正确处理以一个类对象作为另一个类对象的初值,必须合成出一个拷贝构造函数。
2.3 程序转化语义学
显示的初始化操作
- 重写每一个定义,其中的初始化操作会被剥除
- 类的拷贝构造函数调用操作会被按插进去
参数的初始化
- 在编译器实现技术上,有一种策略是导入所谓的的临时性对象,并调用拷贝构造函数将他初始化,然后将此临时性对象交给函数。
- 形式参数必须从原来的类对象,改成类对象的引用。
返回值的初始化
- 首先加上一个额外参数,类型是类对象的一个引用。这个参数用来放置被拷贝建构而得的返回值。
- 在return指令之前安插一个拷贝构造调用操作,以便将欲传回来的对象的内容当作上述新增参数的初值。
成员们的初始化队伍
必须使用member initalization list 的四种情况
- 当初始化一个引用成员时
- 当初始化一个静态成员时
- 当调用一个基类的构造函数,而它拥有一组参数时
- 当调用一个成员类的构造函数,而它拥有一组参数是
注意:list中的项目顺序是由class中的members声明顺序决定的,不是由成员初始化列表中的排列顺序决定的。