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\n", str); 17 int *d = new int(12); 18 printf("%d\n", *d); 19 delete d; 20 printf("%d\n", *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是没怎么理解的。。。)。