• 赋值运算符重载和拷贝构造函数 AND 浅拷贝与深拷贝


    赋值运算符重载: 是用一个已经存在的对象去给另一个已经存在并初始化(调用过构造函数)的对象进行赋值。

    拷贝构造函数:其实本质还是构造函数,用一个已存在的对象去构造一个原先不存在的对象。

    string a("hello");

    string b("world");

    string c =a ;   //拷贝构造函数

    c = b;           //调用赋值函数

    一般来说是在数据成员包含指针对象的时候,应付两种不同的处理需求的 一种是复制指针对象,一种是引用指针对象

    copy大多数情况下是复制,=则是引用对象的     
    例子:  
      class   A  
      {  
              int   nLen;  
              char   *   pData;  
      }  
      显然  
      A   a,   b;  
      a=b的时候,对于pData数据存在两种需求  
      第一种copy  
          a.pData   =   new   char   [nLen];  
          memcpy(a.pData,   b.pData,   nLen);  
      另外一种(引用方式):  
          a.pData   =   b.pData  

    一、拷贝构造函数

    class CExample
    {
    public:
        CExample(){pBuffer=NULL; nSize=0;}
        ~CExample(){delete pBuffer;}
        void Init(int n){ pBuffer=new char[n]; nSize=n;}
    private:
        char *pBuffer; //类的对象中包含指针,指向动态分配的内存资源
        int nSize;
    };


    int main(int argc, char* argv[])
    {
        CExample theObjone;
        theObjone.Init40);
        
        //现在需要另一个对象,需要将他初始化称对象一的状态
        CExample theObjtwo=theObjone;
        ...
    }

    语句"CExample theObjtwo=theObjone;"用theObjone初始化theObjtwo。

    其完成方式是内存拷贝,复制所有成员的值。

    完成后,theObjtwo.pBuffer==theObjone.pBuffer。

    即它们将指向同样的地方,指针虽然复制了,但所指向的空间并没有复制,而是由两个对象共用了。这样不符合要求,对象之间不独立了,并为空间的删除带来隐患。

    提供了拷贝构造函数后的CExample类定义为:

    class CExample
    {
    public:
        CExample(){pBuffer=NULL; nSize=0;}
        ~CExample(){delete pBuffer;}
        CExample(const CExample&); //拷贝构造函数
        void Init(int n){ pBuffer=new char[n]; nSize=n;}
    private:
        char *pBuffer; //类的对象中包含指针,指向动态分配的内存资源
        int nSize;
    };

    CExample::CExample(const CExample& RightSides) //拷贝构造函数的定义
    {
        nSize=RightSides.nSize; //复制常规成员
        pBuffer=new char[nSize]; //复制指针指向的内容
        memcpy(pBuffer,RightSides.pBuffer,nSize*sizeof(char));
    }

    浅拷贝与深拷贝

    用一句简单的话来说就是:浅拷贝,只是对指针的拷贝,拷贝后两个指针指向同一个内存空间;深拷贝不但对指针进行拷贝,

    而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。

    浅拷贝(位拷贝)会出现什么问题呢?

    引起的问题:1:b.m_data 原有的内存未被释放,造成内存泄露

    2:b.m_data和a.m_data指向同一块内存,a或b任何一方变动都会影响另一方,对象不独立了

    3: 对象被析构是,m_data被析构两次。

    实例分析:

    后面部分转载:http://blog.csdn.net/feitianxuxue

     

    浅拷贝:也就是在对象复制时,只是对对象中的数据成员进行简单的赋值,如果对象中存在动态成员,即指针,浅拷贝就会出现问题  

    #include <stdio.h>
      
    class A
    {
     public:
      A() // 构造函数,p指向堆中分配的一空间
     {
       m_data = new char(100);
       printf("默认构造函数 ");
     }
       ~A() // 析构函数,释放动态分配的空间
     {
       if(m_data != NULL)
       {
       delete m_data;
       m_data = NULL;
       printf("析构函数 ");
       }
     }
    private:
       char *m_data; // 一指针成员
    };

    int main()
    {
       A a;
       A b(a); // 复制对象,出现问题
       return 0;
    }

    深拷贝:对于深拷贝,针对成员变量存在指针的情况,不仅仅是简单的指针赋值,而是重新分配内存空间

    #include <stdio.h>
      #include <string>
      
      class A
      {
       public:
       A() // 构造函数,p指向堆中分配的一空间
       {
       m_pdata = new char(100);
       printf("默认构造函数 ");
       }
      
       A(const A& r)
       {
       m_pdata = new char(100); // 为新对象重新动态分配空间
       memcpy(m_pdata, r.m_pdata, strlen(r.m_pdata));
       printf("copy构造函数 ");
       }
      
       ~A() // 析构函数,释放动态分配的空间
       {
       if(m_pdata != NULL)
       {
       delete m_pdata;
       printf("析构函数 ");
       }
       }
      
       private:
       char *m_pdata; // 一指针成员
      };
      
      int main()
      {
       A a;
       A b(a); // 复制对象,不仅是数据成员的赋值,内存空间重分配
       return 0;
      }



    博客内容只为本人学习所感转载亦或自写,不足或错误之处请大家不吝赐教
  • 相关阅读:
    Mac怎样通过终端开启/关闭SSH?Mac开启和关闭SSH新手教程
    Linux安装搜狗拼音和谷歌拼音输入法
    用git按需下载github仓库部分/单个文件夹的方法
    程序填空_2
    程序填空_1
    c语言 在已排序的数组中插入一个数,仍保持排序状态
    程序填空_3
    c语言 冒泡排序
    spark 文件位置报错
    Resources are low on NN. Please add or free up more resources then turn off safe mode manually.
  • 原文地址:https://www.cnblogs.com/niupan369/p/4487142.html
Copyright © 2020-2023  润新知