赋值运算符重载和拷贝构造函数 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;
  }



博客内容只为本人学习所感转载亦或自写,不足或错误之处请大家不吝赐教
原文地址:https://www.cnblogs.com/niupan369/p/4487142.html