关于对象的拷贝,大部分时间我们用的都是浅拷贝,比如赋值符号(“=”)以及memcpy()等。那么既然浅拷贝这么简单,为什么还需要深拷贝呢?两者之间的区别又是什么呢?两者分别在什么情况下使用呢?
可能很多人写了很久的代码,都还只知道对象赋值而不知道深拷贝,导致很多时间出现莫名bug而且找不到原因。今天就让我们深入的来了解一下两者的区别。
浅拷贝
例如:
class MyClass{public:MyClass(int x);~MyClass();int a ;private:};MyClass::MyClass(int x){this->a = x ;}MyClass::~MyClass(){}void main(){int b = 100 ;//浅拷贝MyClass my1(10) ;MyClass my2 = my1;//浅拷贝MyClass my3(20) ;memcpy(&my3,&my1,sizeof(MyClass));//浅拷贝cout<
运行结果是都是10,以上三个都是浅拷贝,浅拷贝的原理就是:将 被拷贝对象所在内存中的数据按照二进制位(Bit)复制到新对象所在的内存,这种默认的拷贝行为就是浅拷贝。其原理图如下:
浅拷贝的缺点
上面的例子中,MyClass都是基本类型,这种浅拷贝用起来是没有什么问题,但是C++的难点是什么?对,就是指针。如果MyClass成员中有指针类型怎么办?是不是也用浅拷贝呢?
我们在Mycalss类中新增一个char* str 成员,还是按上面那样用浅拷贝的方式拷贝对象。
class MyClass{public:MyClass(int x,char * s);~MyClass();int len;int a ;char* str ;private:};MyClass::MyClass(int x,char* s ,int length){//这里注意不能直接this->str = s ;因为指向的是常量,常量内存我们是delete不了的this->len = lenth ;this->a = x ;this->str = new char[this->len] ;memcpy(str,s,this->len);}MyClass::~MyClass(){}void main(){int b = 100 ;//浅拷贝MyClass my1(10,"i love u") ;MyClass my2 = my1;//浅拷贝MyClass my3(20,"i do not love u") ;memcpy(&my3,&my1,sizeof(MyClass));cout<
我们发现my2.str和my3.str打印出来的是一堆乱码。这是为什么呢?请看下面的示意图:
浅拷贝复制的只是指针变量,但是这个指针所管理的内存还是my1的。所以当你通过my1删除了str所管理的内存,那么在my2和my3中的str就找不到这块内存原来的内容了;
深拷贝的实现
既然浅拷贝在对象中存在着管理其他内存的指针时,在对象的内存释放时会出现野指针的问题,那么如何去避免呢?很简单,除了会将原有对象的所有成员变量拷贝给新对象,还会为新对象再分配一块内存,并将原有对象所持有的内存也拷贝过来。
实现代码:
#include #include #include #include using namespace std;class MyClass{public:MyClass(int x,char * s,int len);MyClass(const MyClass& myclass);~MyClass();int len ;int a ;char* str;private:};MyClass::MyClass(int x, char* s,int length){this->len = length ;this->a = x ;this->str = new char[this->len] ;memcpy(str,s,this->len);}MyClass::MyClass(const MyClass& myclass){this->len = myclass.len ;this->a = myclass.a ;this->str = new char[this->len] ;memcpy(this->str,myclass.str,this->len);}MyClass::~MyClass(){}void main(){cout<