浅拷贝和深拷贝
深拷贝和浅拷贝是C++中用于对象拷贝的两种方式,拷贝后,新对象将具有一份和原始对象完全对应的属性,主要区别在于它们处理属性中的引用类型(动态分配的内存指针)的方式不同。
浅拷贝(Shallow Copy)
定义:浅拷贝是按位拷贝对象。
如果属性是基本类型,新对象将真实拷贝基本类型的值,与原始对象的基本类型属性间相互独立,互不影响;
如果属性是引用类型(动态分配的内存指针),新对象将拷贝该引用(指针)作为自己的属性,但是其指向的真实内存空间(堆内存)与源对象相比是同一块内存空间,因此如果其中一个对象改变了这个地址,就会影响到另一个对象。
针对基本类型和引用类型数据的区别可以自行百度。
在浅拷贝中,只复制对象中的数据成员的值,而不复制指向动态分配内存的指针。这样,原始对象和拷贝对象共享同一块内存资源。如果一个对象的析构函数被调用,可能会导致两个对象同时释放同一块内存,从而引起内存错误。
浅拷贝适用于基本类型数据和简单对象(对象中不包含动态分配内存)的情况。
class Base{
public:
Base(): m_a(0), m_b(0){ }
Base(int a, int b): m_a(a), m_b(b){ }
private:
int m_a;
int m_b;
};
int main(){
int a = 10;
int b = a; //拷贝
Base obj1(10, 20);
Base obj2 = obj1; //拷贝
return 0;
}
b 和 obj2 都是以拷贝的方式初始化的,具体来说,就是将 a 和 obj1 所在内存中的数据按照二进制位(Bit)复制到 b 和 obj2 所在的内存,这种默认的拷贝行为就是浅拷贝,这和调用 memcpy() 函数的效果非常类似。
对于简单的类,默认的拷贝构造函数一般就够用了,我们也没有必要再显式地定义一个功能类似的拷贝构造函数。但是当类持有其它资源时,例如动态分配的内存、指向其他数据的指针等,默认的拷贝构造函数就不能拷贝这些资源了,我们必须显式地定义拷贝构造函数,以完整地拷贝对象的所有数据,这就是深拷贝。
深拷贝(Deep Copy)
定义:深拷贝会拷贝所有的属性,而且也会拷贝属性指向的动态分配的内存。当对象和它所引用(指向)的对象一起拷贝时即发生深拷贝。深拷贝相比于浅拷贝速度较慢并且花销较大。
在深拷贝中,不仅复制数据成员的值,还要复制指向动态分配内存的指针所指向的实际数据。这样,原始对象和拷贝对象拥有各自独立的内存资源,不会相互影响。
深拷贝通常需要自定义拷贝构造函数和赋值运算符重载函数。
在这些函数中,必须显式地分配内存,并将原始对象中的数据复制到新分配的内存中。深拷贝适用于对象中包含动态分配内存的情况,可以避免因共享内存资源而引起的错误。