如果一个类拥有资源,该类的对象进行复制时,如果资源重新分配,就是深拷贝,否则就是浅拷贝。
- 深拷贝: 该对象和原对象占用不同的内存空间,既拷贝存储在栈空间中的内容,又拷贝存储在堆空间中的内容。
- 浅拷贝: 该对象和原对象占用同一块内存空间,仅拷贝类中位于栈空间中的内容。
当类的成员变量中有指针变量时,最好使用深拷贝。因为当两个对象指向同一块内存空间,如果使用浅拷贝,当其中一个对象的删除后,该块内存空间就会被释放,另外一个对象指向的就是垃圾内存。
#include <iostream>
using namespace std;
class Test
{
private:
int *p;
public:
Test(int tmp)
{
this->p = new int(tmp);
cout << "Test(int tmp)" << endl;
}
void set(int v){
*p = v;
}
int get(){
return *p;
}
~Test()
{
if (p != NULL)
{
delete p;
}
cout << "~Test()" << endl;
}
};
int main()
{
Test ex1(10);
Test ex2 = ex1;
ex1.set(20);
cout << "ex2:" << ex2.get();
return 0;
}
/*
运行结果:
Test(int tmp)
ex2:20
~Test()
*/
说明: 上述代码中,类对象 ex1、ex2 实际上是指向同一块内存空间,修改ex1的数据成员,ex2的也会同时改变。对象析构时,ex2 先将内存释放了一次,之后 析构对象 ex1 时又将这块已经被释放过的内存再释放一次。对同一块内存空间释放了两次,会导致程序崩溃。
若进行深拷贝,则可以解决上述情况:
#include <iostream>
using namespace std;
class Test
{
private:
int *p;
public:
Test(int tmp)
{
p = new int(tmp);
cout << "Test(int tmp)" << endl;
}
void set(int v){
*p = v;
}
int get(){
return *p;
}
~Test()
{
if (p != NULL)
{
delete p;
}
cout << "~Test()" << endl;
}
Test(const Test &tmp) // 定义拷贝构造函数
{
p = new int(*tmp.p);
cout << "Test(const Test &tmp)" << endl;
}
};
int main()
{
Test ex1(10);
Test ex2 = ex1;
ex1.set(20);
cout << "ex2:" << ex2.get();
return 0;
}
/*
Test(int tmp)
Test(const Test &tmp)
ex2:10
~Test()
~Test()
*/