深拷贝与浅拷贝
浅拷贝就是镜子里的你,
深拷贝就是克隆一个的你。
浅拷贝只是引用拷贝对象,而不独立开辟内存区,深拷贝则要开辟内存区,并且复制被拷贝对象
的数据。
浅拷贝和深拷贝的问题多发生在指针变量或者包含指针类型成员的类的对象之间。
先看一个简单例程:
#include <iostream>
using namespace std;
int main()
{
int *p1 = new int(88), *p2; //定义两个整型指针变量
cout < < "p1= " < < p1 < < ", p2= " < < p2 < <endl; //在屏幕上输出p1 和 p2
p2 = p1; //语句1:浅拷贝在此发生了
delete p1;
delete p2; //语句2:报错! 由于两个指针变量之间的浅拷贝导致所指向的内存二次释放
cout < < "p1= " < < p1 < < ", p2= " < < p2 < <endl;
return (0);
}
大家可以看到,语句1进行的操作只是将地址进行了复制,语句执行后,p1和p2指向了同一块内存。
之后的delete操作使p1所指向的内存被释放,接下来“灾难”来了,因为p2所指向的内存已经在之前就被释放了,
而语句2有要将那块已经释放的内存再次释放,笨笨的计算机倍感诧异,于是程序报错,异常终止。
语句1所体现的操作就称为“浅拷贝”,此谓“浅”给人感觉就是表面上的一种拷贝,
只是原原本本地将指针变量存储的地址进行了复制。而解决这种问题的办法就是“深拷贝”,
即将指针变量所指向的内存也作一个拷贝,大家各一份,谁也别抢谁的,即:
#include <iostream>
using namespace std;
int main()
{
int *p1 = new int(88), *p2; //定义两个整型指针变量
cout < < "p1= " < < p1 < < ", p2= " < < p2 < <endl; //在屏幕上输出p1 和 p2
p2 = new int(88);
*p2 = *p1; //语句3:深拷贝
//p2 = p1; //语句1:浅拷贝
delete p1;
delete p2; //各释放各的内存,互不打扰
cout < < "p1= " < < p1 < < ", p2= " < < p2 < <endl;
return (0);
}
语句3就是将p1所指向的内存作了拷贝给p2,一人一块。
以上是一个简单而直接的例子来说明浅拷贝和深拷贝的问题,而大多数时候这个问题是隐蔽地发生在含有指针类型成员的类的对象
之间的。在用一个类的对象实例化另一个对象时(如:obj2(obj1);),如果使用缺省的拷贝构造函数来实例化,则是一种浅拷贝,
如要达到深拷贝的效果,则应该自定义一个拷贝构造函数来手动实现。当然,如果类中没有指针类型的成员,则没有这个必要,
但如果有的话,还是很有这个必要的。