• 深度探索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是没怎么理解的。。。)。

  • 相关阅读:
    Hyper-V无法启动虚拟机因为虚拟机监控程序未运行
    SpringBoot项目中自动加载datasourceConfig配置导致启动失败
    redis 数据类型与命令
    Redis入门与安装,与配置
    MySQL 主从配置
    MySql 中的事务
    什么是Docker?
    window10下安装Docker
    Docker 常见命令
    原生SQL语句
  • 原文地址:https://www.cnblogs.com/lthb/p/6636525.html
Copyright © 2020-2023  润新知