构造函数,拷贝构造和赋值运算符‘=‘的区别

例子

class CExample  

{

private: 

  char *pBuffer;   //类的对象中包含指针,指向动态分配的内存资源 

  int nSize; 

public:  

  CExample()   {pBuffer=NULL;nSize=0;}

  ~CExample()  {delete pBuffer;}  

  void Init(int n)  { pBuffer=new char[n]; nSize=n;}

};   

int main( )  

 {   

CExample theObjone;           //对象创建调用构造函数

theObjone.Init(40);    

CExample theObjtwo=theObjone; //对象复制(因初始化),调用拷贝构造函数

        (有指针成员,使用默认拷贝构造有缺点(仅复制指针),故要用自定义的)

CExample theObjthree;  

theObjthree.Init(60);   

theObjthree=theObjone;        //对象赋值操作(因非初始化),调用赋值运算符

         (有指针成员,使用默赋值符“=”有缺点(旧指针被丢弃),故要重载运算符)

}

注意:"="号的两种不同使用,初始化和赋值

第三行也用到了"="号,该"="在对象声明语句中,表示初始化。更多时候,这种初始化也可用括号()表示。而最后一行的"="号是赋值符,使用默认赋值符"=",是把被赋值对象的原内容被清除,并用右边对象的内容填充。

构造函数  主要用来在创建对象时, 即为对象成员变量赋初始值 

拷贝构造函数 形式为X(X&),用来完成基于同一类的其他对象的构建及初始化

一个对象需要通过另外一个对象进行初始化,调用拷贝构造函数。

初始化和赋值的不同含义是构造函数调用的原因。事实上,拷贝构造函数是由普通构造函数和赋值操作符共同实现的

默认拷贝构造函数(浅拷贝)

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

调用默认拷贝构造含,  其完成方式是内存拷贝(浅拷贝),复制所有成员的值。

完成后,theObjtwo.pBuffer==theObjone.pBuffer。   即它们将指向同样的地方,指针虽然复制了,但所指向的空间并没有复制,而是由两个对象共用了。

这样不符合要求,对象之间不独立了,并为空间的删除带来隐患(产生野指针

自定义拷贝构造函数(深拷贝)

因此可以在构造函数中添加操作来解决指针成员的问题,即自定义的拷贝构造函数   

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

这样,定义新对象,并用已有对象初始化新对象时,CExample(const CExample& RightSides)将被调用,而已有对象用别名RightSides传给构造函数,以用来作复制。    

原则上,应该为所有包含动态分配成员的类都提供自定义的拷贝构造函数。

注意:内存拷贝函数void *memcpy(void *dest, constvoid *src, size_t n)

默认赋值操作符"="

//赋值操作符重载  
CExample & CExample::operator = (const CExample& RightSides)   
{   
 nSize=RightSides.nSize;      //复制常规成员   
 char *temp=new char[nSize];//复制指针指向的内容(默认=的缺点)   
 memcpy(temp,RightSides.pBuffer,nSize*sizeof(char));   
 delete []pBuffer;    //删除原指针指向内容(避免内存泄露)
          
 pBuffer=NULL;     //同时把原指针置为NULL(避免野指针)
 pBuffer=temp;      //建立新指向  
 return *this ;
}  

"="的缺省(默认)操作只是将成员变量的值相应复制,旧的值被自然丢弃    

最后一行的"="表示赋值操作,将对象theObjone的内容复制到对象theObjthree,这其中涉及到对象theObjthree原有内容的丢弃,新内容的复制。   

由于对象内包含指针,将造成不良后果:指针的值被丢弃了,但指针指向的内容并未释放(导致内存泄露)。指针的值被复制了,但指针所指内容并未复制(导致新指针指的内容丢了

即产生两方面的问题:丢弃旧指针(导致内存泄露),仅复制新指针(导致内容丢了)

因此,包含动态分配成员的类除了提供拷贝构造函数外,还应该考虑重载"="赋值操作符号

重载"="赋值操作符

--------------------- 本文来自 日月行者 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/qq_16445683/article/details/46043505?utm_source=copy

猜你喜欢

转载自blog.csdn.net/venice0708/article/details/82876907