• 深拷贝和浅拷贝(一)


    1. 浅拷贝

        所谓浅拷贝,指的是在对象复制时,只对对象的数据成员进行复制,但是遇到有动态成员如指针时就会出问题。

    [c-sharp] view plain copy
     
    1. class Rect  
    2. {  
    3. public:  
    4.     Rect()      // 构造函数,p指向堆中分配的一空间  
    5.     {  
    6.         p = new int(100);  
    7.     }  
    8.     ~Rect()     // 析构函数,释放动态分配的空间  
    9.     {  
    10.         if(p != NULL)  
    11.         {  
    12.             delete p;  
    13.         }  
    14.     }  
    15. private:  
    16.     int width;  
    17.     int height;  
    18.     int *p;     // 一指针成员  
    19. };  
    20.   
    21. int main()  
    22. {  
    23.     Rect rect1;  
    24.     Rect rect2(rect1);   // 复制对象  
    25.     return 0;  
    26. }  

        在这段代码运行结束之前,会出现一个运行错误。原因就在于在进行对象复制时,对于动态分配的内容没有进行正确的操作。我们来分析一下:

        在运行定义rect1对象后,由于在构造函数中有一个动态分配的语句,因此执行后的内存情况大致如下:

     

     

        在使用rect1复制rect2时,由于执行的是浅拷贝,只是将成员的值进行赋值,这时 rect1.p= rect2.p,也即这两个指针指向了堆里的同一个空间,如下图所示:

    在销毁对象时,两个对象的析构函数将对同一个内存空间释放两次。我们需要的不是两个p有相同的值,而是两个p指向的空间有相同的值,解决办法就是使用“深拷贝”。


    3. 深拷贝

        在“深拷贝”的情况下,对于对象中动态成员,就不能仅仅简单地赋值了,而应该重新动态分配空间,如上面的例子就应该按照如下的方式进行处理:

    [c-sharp] view plain copy
     
    1. class Rect  
    2. {  
    3. public:  
    4.     Rect()      // 构造函数,p指向堆中分配的一空间  
    5.     {  
    6.         p = new int(100);  
    7.     }  
    8.     Rect(const Rect& r)  
    9.     {  
    10.         width = r.width;  
    11.         height = r.height;  
    12.         p = new int;    // 为新对象重新动态分配空间  
    13.         *p = *(r.p);  
    14.     }  
    15.     ~Rect()     // 析构函数,释放动态分配的空间  
    16.     {  
    17.         if(p != NULL)  
    18.         {  
    19.             delete p;  
    20.         }  
    21.     }  
    22. private:  
    23.     int width;  
    24.     int height;  
    25.     int *p;     // 一指针成员  
    26. };  

    此时,在完成对象的复制后,内存的一个大致情况如下:

     

    此时rect1的p和rect2的p各自指向一段内存空间,但它们指向的空间具有相同的内容,这就是所谓的“深拷贝”。

     

  • 相关阅读:
    如何阅读论文
    我的算法学习之路
    blazor wasm访问非本地的restful service
    ionic + asp.net core webapi + keycloak实现前后端用户认证和自动生成客户端代码
    在ef core中使用postgres数据库的全文检索功能实战之中文支持
    在ef core中使用postgres数据库的全文检索功能实战
    .net core grpc单元测试
    asp.net core + entity framework core 多数据库类型支持实战
    asp.net core计划任务探索之hangfire+redis+cluster
    Keycloak & Asp.net core webapi 整合跳坑之旅
  • 原文地址:https://www.cnblogs.com/zzdbullet/p/9949749.html
Copyright © 2020-2023  润新知