The Semantics of Constructors——2.2 拷贝构造函数的构造操作
The Semantics of Constructors
2.2.1 Default Memberwise Initialization(默认的逐成员初始化)
如果class没有提供一个explicit copy constructor又当如何?当class object 以“相同 class 的另一个 object”作为初值,其内部是以所谓的 default memberwise initialization手法完成的,也就是把每一个内建的或派生的data member(例如一个指针或一个数组)的值,从某个object拷贝一份到另一个object身上。不过它并不会拷贝其中的 member class object,而是以递归的方式施行 memberwise initialization。
copy constructors在必要的时候才由编译器产生出来。这个句子中的“必要”意指当 class 不展现 bitwise copy semantics 时。
2.2.2 什么时候不会Bitwise Copy Semantics(位逐次拷贝)?
(什么时候编译器会合成copy constructors呢?)
什么时候一个class不展现出“bitwise copy semantics”呢?有4种情况:
-
当class内含一个member object 而后者的class声明有一个copy constructor时(不论是被 class设计者显式地声明,就像前面的 String那样;或是被编译器合成,像 class Word那样)。
-
当 class继承自一个 base class而后者存在一个 copy constructor时(再次强调,不论是被显式声明或是被合成而得)。
-
当 class声明了一个或多个 virtual functions时。
-
当 class派生自一个继承串链,其中有一个或多个 virtual base classes时。
在前两种情况中,编译器必须将member或base class的“copy constructors调用操作”安插到被合成的copy constructor 中。
2.2.3 重新设定 Virtual Table的指针
1. 同类型之间的拷贝
//Bear有虚函数
Bear yogi;
Bear winnie = yogi;
会直接把yogi的vptr值拷贝给winnie,两个对象的虚函数指针指向相同的虚函数表。
2. 用派生类初始化基类
//ZooAnimal 是Bear的基类
ZooAnimal franny = yogi; //会发生sliced
合成出来的ZooAnimal copy constructor 会显式设定object的vptr指向ZooAnimal class的virtual table,而不是直接从右手边的class object中将其vptr现值拷贝过来。
2.2.4 处理 Virtual Base Class Subobject
虚基类——Raccoon
虚基类的派生类——RedPanda
- 如果用一个虚基类Raccoon对象初始化另一个Raccoon对象,那么直接“bitwise copy”就可以了。
- 如果用一个虚基类的派生类RedPanda对象初始化一个Raccoon虚基类时:在这种情况下,为了完成正确的 little_critter 初值设定,编译器必须合成一个copy constructor,安插一些代码以设定virtual base class pointer/offset 的初值(或只是简单地确定它没有被抹消),对每一个members执行必要的memberwise初始化操作,以及执行其他的内存相关工作。
little_red和little_critter的关系: