在C++中,对象复制分为浅复制和深复制。
(1)对象的浅复制
当两个对象之间进行复制时,若复制完成后它们还共享某些内存空间,其中一个对象的销毁会影响到另一个对象,这种对象之间的复制称为浅复制。
(2)对象的深复制
当两个对象之间进行复制时,若复制完成后它们不会共享任何内存空间,其中一个对象的销毁不会影响到另一个对象,这种对象之间的复制称为深复制。
通常情况下拷贝构造函数执行的都是浅复制,当有必要时,我们可以自己写一个拷贝构造函数实现深复制。当一个类中的数据成员带有指针时,此时使用默认的拷贝构造函数,类对象的指针数据成员经过浅复制后会指向同一块内存区域,表面上看上去仿佛没事,但一旦销毁其中任意一个对象时,会调用该类的析构函数,那么指针指向的那块内存区域会被回收,此时再访问另一个对象时,这个对象的指针数据成员所指地址的内存区域已经被回收,会产生未定义的结果,要解决这个问题,我们需要重写拷贝构造函数,实现深复制。实现深复制只需要在该类的拷贝构造函数中,动态分配一块大小和被复制的对象的指针指向的内存区域相同大小的内存区域,将数据复制过去,并将指针指向刚刚分配的内存区域即可。
如下为String 类的基本实现,用到了深复制。
class String{ public: String(const char *str = NULL);//构造函数 String(const String &other);//拷贝构造函数 ~String(void);//析构函数 String & operator = (const String &other);//重载赋值运算符 private: char *m_data;//用于保存字符串 }; String::String(const char *str )//构造函数 { if(str == NULL){ m_data = new char[1]; *m_data = '\0'; } else{ int length = strlen(str); m_data = new char[length+1]; strcpy(m_data,str); } } String::String(const String &other)//拷贝构造函数 { int length = strlen(other.m_data); m_data = new char[length+1]; strcpy(m_data,other.m_data); } String::~String(void)//析构函数 { delete m_data; } String &String :: operator = (const String &other)//重载赋值运算符 { if(this==&other){//检查自赋值 return *this; } delete m_data; int length = strlen(other.m_data); m_data = new char[length+1]; strcpy(m_data,other.m_data); return *this; }