深度探索c++对象模型读书笔记:构造函数语义学-位逐次拷贝

Bitwise Copy(位逐次拷贝)出现原因:

  一个良好的编译器可以为大部分class objects产生bitwise copise(位逐次拷贝),因为它们有bitwise copy semantics(位逐次拷贝语意)。

Bitwise Copy会导致程序出现的bug:

 1 //构造函数语意学-位逐次拷贝构造函数
 2 #include <bits/stdc++.h>
 3 using namespace std;
 4 class String
 5 {
 6 public:
 7     String()
 8     {
 9         len = 10;
10         str = new char[10];
11         str[0] = 'H';
12         str[1] = 'e';
13     }
14     void print()
15     {
16         printf("%s
", str);
17         int *d = new int(12);
18         printf("%d
", *d);
19         delete d;
20         printf("%d
", *d); //真是神奇的地方,这儿竟然不会使程序崩溃,难道是因为d对应的内存地址还没有被别的东西使用,所以就可以输出么,反正如果乱指一个地方是很有可能使程序崩溃的
21     }
22     ~String()
23     {
24         delete[] str;
25     }
26     int len;
27     char *str;
28 };
29 int main()
30 {
31     String *str = new String();
32     str->print();
33     String str2 = *str;//这儿显然就用了位逐次拷贝构造函数了,所以此时有str2::str = str::str,即它们的内存地址相同
34     str2.print();
35     delete str;//当str::str被delete之后,str2::str也就被delete了,所以输出会出问题
36     str2.print();
37     return 0;
38 }

Bitwise Copy具体实现:

  当复制一个对象的时候,直接对该对象的每一个非静态成员变量进行复制。

一个class不展现出"bitwise copy semantics"的四种情况:

  1.当class内含一个menber 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需要编译器合成拷贝构造函数的原因:指向virtual function table(vtb1)的指针vptr需要正确的设置好初值而不能简单的复制。

  比如当一个base class object(而不是对象的指针)以其derived class(派生类)的object内容做初始化操作时,vptr显然就不能进行简单的复制。此时的base class copy constructor必须显示设定object的vptr指向base class的virtual table。

  情况4需要编译器合成拷贝构造函数的原因:编译器必须显式的将被赋值对象的virtual base class pointer/offset初始化。在这种情况下,为了完成正确的目标对象初值设定,编译器必须合成一个copy constructor,安插一些代码以设定virtual base class pointer/offset的初值(或者只是简单的确定它没有被抹消),对每一个members执行必要的memberwise初始化操作,以及执行其他的内存相关工作(其实我自己对于情况4是没怎么理解的。。。)。