如果一个类拥有资源,该类的对象进行复制时,如果资源重新分配,就是深拷贝,否则就是浅拷贝。
深拷贝:该对象和原对象占用不同的内存空间,即拷贝存储在栈空间中的内容,又拷贝存储在堆空间中的内容。
浅拷贝:该对象和原对象占用同一块内存空间,仅拷贝类中位于栈空间的内容。
当类的成员变量中有指针变量时,最好使用深拷贝。因为当两个对象指向同一块内存空间,如果使用浅拷贝,当其中一个对象资源释放后(调用析构函数),对象指针指向的内存空间也被释放,此时另一个对象指向的就是垃圾内存。
浅拷贝实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| #include <iostream> using namespace std;
class Test { int *p; public: Test(int temp) { this->p = new int(temp); cout << "Test(int temp)" << endl; } ~Test() { if (p != nullptr) delete p; cout << "~Test()" << endl; } };
int main() { Test ex1(10); Test ex2 = ex1; return 0; }
|
上述代码中,类对象 ex1、ex2 实际上指向同一块内存空间,对象析构时,ex2 先将内存释放了一次,之后析构对象 ex1 时又将这块已经释放过的内存再释放一次。对同一块内存空间释放了两次,会导致程序崩溃。
深拷贝实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| #include <iostream> using namespace std;
class Test { int *p; public: Test(int temp) { this->p = new int(temp); cout << "Test(int temp)" << endl; } Test(const Test& temp) { p = new int(*temp.p); cout << "Test(const Test& temp)" << endl; } ~Test() { if (p != nullptr) delete p; cout << "~Test()" << endl; } };
int main() { Test ex1(10); Test ex2 = ex1; return 0; }
|
编译器生成的默认拷贝构造函数大部分都是浅拷贝,所以再特定场景下需要禁止编译器生成默认拷贝构造函数。再遇到需要使用堆内存的构造函数中,我们需要特别注意浅拷贝和深拷贝的使用方式,防止两个不同的对象指向同一块内存区域。
参考
深拷贝和浅拷贝的区别