默认构造函数:
- 什么是trival-default constructor,什么是non-trival default constructor两者的差别在哪?
- 简单言之,trival的默认构造函数只是能让代码通过编译,而其它什么事都不做,而non-trival的默认构造函数则相反,non-trival的构造函数还会进行一些其它的动作,比如初始化class object的virtual function table。
- 并不是我们所理解的任何没有构造函数的类都会自动创建,不需要的时候只是有trival default constructor,而在编译器觉得需要的时候,会生成nontrival default constructor有以下四种情况:
- 如果 class A 内含 member class objects,那么 class A的每一个 constructor必须调用每一个 member classes 的 default constructor。如果没有,则会生成默认的构造函数,如果有但不全,编译器会扩张已存在的 constructors,在其中安插一些代码,使得member class的default constructor被调用。
- 派生自含有default constructor的class,也会自动生成。
- 声明或继承了virtual函数的class。会有虚函数表和指针生成。
- 以及派生自一个继承链,其中有virtual base class。virtual base class在这个class中是以指针的形式,构造函数完成这个工作的。
拷贝构造函数:
- 显示拷贝构造的时候,函数传参、函数返回值的时候都会用到这个函数。
- 如果没有显示定义,且不符合逐位拷贝规则 Bitwise Copy Semantics的,则会生成non-trival 默认拷贝构造函数。将每个内建类型的成员变量从一个对象拷贝到另一个对象,将class成员变量,通过递归调用其拷贝构造的方式拷贝。
- 不符合Bitwise Copy Semantics 的规则与上面的类似,四种:
- 成员变量有非默认构造函数的;
- 继承的类有非默认构造函数的;这两种都是因为需要调用其拷贝构造,而不是逐位拷贝,所以需要生成。
- 虚函数的,涉及到虚指针的拷贝,在继承体系里面的copy构造,如果直接将vptr直接copy,可能会将derived的vptr,拷贝到base类的vptr,这样肯定是不行的,所以需要拷贝构造函数来手动设置自己类的vptr。
- 虚继承的,与上面类似。
返回值优化:
- Named Return Value优化(NRV优化):在返回值以value形式返回时,多重的拷贝是低效的,则编译器自动将函数优化为传入一个引用,直接在引用上构建返回值,最终返回值为void。但这个建立在有一个被显示声明的拷贝构造函数的基础上。
- 那么一般情况下,如果不符合上面的四种情况,bitwise的拷贝构造效率很高,但是如果有大量的传值返回的函数时,那么也可以考虑自定义一个memcpy的拷贝构造,保持一定效率的情况下,让编译器可以对返回值进行优化。
成员初始化列表:
- 效率上会比较高,会直接构建成员,而不是默认构造函数之后再加一个拷贝构造。编译器会在所有用户代码之前将这个初始化变成语句来直接构造成员变量。
- 初始化的顺序不是按照初始化列表里写的,而是按照声明时的顺序,所以别出错。