深拷贝
默认拷贝构造函数
声明一个class的时候,编译器会自动为class补全一个拷贝构造函数,这个拷贝构造函数将原对象的成员拷贝到新的对象的成员。比如这样一个代码
class A {
private:
int a;
int b;
public:
...
}
默认的拷贝构造函数会把原来对象的a和b都复制一个副本放在新的对象里。
默认拷贝构造函数的缺陷
然而如果这个对象中有额外分配的内存空间,并且将自身的数据储存在这个内存块里(比如用指针指向的内存空间),这样的拷贝只会将指针复制为一个新的指针,但是两个指针所指向的内存空间是同一个内存块,这样的话在对任何一个对象的指针进行操作时,会对另一个对象的数据同时进行修改;对任意一个对象的内存空间进行回收时,也会影响另一个对象。比如这个class
class B {
private:
int a;
int* str;
int str_len;
public:
...
}
如果使用默认拷贝构造函数的话,则新的对象的a和原对象的a相等,新的str也和原来的str相等,即指向同一块内存。这样对原来的str回收或修改以后,新的对象的str也发生了改变,这个改变可能是不可控的。
因此我们选择自己重载拷贝构造函数,为新的对象开辟新的内存空间,新对象的str和旧对象的str指向不同的内存块,但是两个内存中的内容是相同的, 我们把这种拷贝方式叫做深拷贝,这是相对于上边那种浅拷贝而言的。
深拷贝
B& B::B(B& from) {
this->str = new int;
*(this->str) = *(from.str);
}
还是用B类作为例子,这时新对象的str和原对象的str所指向的值是相同的,但是他们分别指向不同的内存空间,拥有独立的储存。对于其他对象修改和清除时也不会发生内存的泄露或产生指向空内存的野指针,我们完成了一次深拷贝。