例子:
老师给你们留了作业,你们班只有小A一个人会写,其他人都需要copy他的作业。
如果你们都是通过浅拷贝来完成作业,那么就相当与“在你需要的时候,小A会把作业借给你”。
例 如,老师对小B说“去把你的作业拿来给我看看”,小B赶快找小A借作业给老师看。老师又要看小C的作业,小C也只能找小A借过来应付老师。总之老师如果一 个一个的检查作业,你们都能应付,因为你们只有一本作业互相借着看一下就OK了。如果老师说“全班把作业一起交上来”,那你们就完蛋了。
深拷贝就是每个人都实实在在的抄了一份作业,每个人的作业都是自己抄来的,所以老师收全班的作业你们也不怕,要多少本就给他多少.
浅拷贝和深拷贝之间的区别:浅拷贝是指将对象中的数值类型的字段拷贝到新的对象中,而对象中的引用型字段则指复制它的一个引用到目标对象。如果改变目标对 象中引用型字段的值他将反映在原始对象中,也就是说原始对象中对应的字段也会发生变化。深拷贝与浅拷贝不同的是对于引用的处理,深拷贝将会在新对象中创建 一个新的和原是对象中对应字段相同(内容相同)的字段,也就是说这个引用和原是对象的引用是不同的,我们在改变新对象中的这个字段的时候是不会影响到原始 对象中对应字段的内容。所以对于原型模式也有不同的两种处理方法:对象的浅拷贝和深拷贝。
所以使用浅拷贝,对于对象的引用成员,仅仅是拷贝了它的引用,修改拷贝对象的引用成员也会同时修改原对象的相应成员。而深拷贝则是一直拷贝到值类型成员为 止。个人理解,如果要对一个链表进行深拷贝,则需要创建这个链表中的所有表节点对象,再将这些对象依照原来的关系连接起来,这时存在两条链表,内存中增加 了一倍的存储(增加了n个对象引用,以及为这些对象分配的n个空间)。而如果进行浅拷贝,只是拷贝了一个链表对象引用,并为这个引用分配了相应的空间,内 存中仅仅是多了一个对象的引用(4个字节,栈区分配)以及一个对象(堆区分配)。
我们首先要知道默认拷贝构造函数可以完成对象的数据成员简单的复制,这也称为浅拷贝。对象的数据资源是由指针指向的堆时,默认的拷贝构造函数只是将指针复制。
a. 我们首先分析下面的代码为什么会出错??
class Test
{
private:
int* p;
public:
Test(int x)
{
this->p=new int(x);
cout << "对象被创建" << endl;
}
~Test()
{
if (p != NULL)
{
delete p;
}
cout << "对象被释放" << endl;
}
int getX() { return *p; }
};
int main()
{
Test a(10);
//会调用默认的拷贝构造函数
Test b = a;
return 0;
}
我们画一个示意图分析:
看懂了示意图,我们知道为什么会出错了(同一个内存被释放两次)。我们接下来分析解决方案:
class Test
{
private:
int* p;
public:
Test(int x)
{
this->p=new int(x);
cout << "对象被创建" << endl;
}
~Test()
{
if (p != NULL)
{
delete p;
}
cout << "对象被释放" << endl;
}
int getX() { return *p; }
//深拷贝(拷贝构造函数)
Test(const Test& a)
{
this->p = new int(*a.p);
cout << "对象被创建" << endl;
}
//浅拷贝(拷贝构造函数)
//Test(const Test& a)
//{
// this->p = a.p;
// cout << "对象被创建" << endl;
//}
};
int main()
{
Test a(10);
//我们手动的写拷贝构造函数,C++编译器会调用我们手动写的
Test b = a;
return 0;
}
总结: 浅拷贝会把指针变量的地址复制; 深拷贝会重新开辟内存空间。