浅拷贝就比如像引用类型,而深拷贝就比如值类型。
浅拷贝是指源对象与拷贝对象共用一份实体,仅仅是引用的变量不同(名称不同)。对其中任何一个对象的改动都会影响另外一个对象。举个例子,一个人一开始叫张三,后来改名叫李四了,可是还是同一个人,不管是张三缺胳膊少腿还是李四缺胳膊少腿,都是这个人倒霉。
深拷贝是指
源对象与拷贝对象互相独立
,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。比较典型的就是Value(值)对象,如预定义类型Int32,Double,以及结构(struct),枚举(Enum)等。
浅拷贝就是对象的数据成员之间的简单赋值,
如你设计了一个没有类而没有提供它的复制构造函数,当用该类的一个对象去给令一个对象赋值时所执行的过程就是浅拷贝,如:
#include <iostream>
using namespace std;
class A
{
public:
A(int _data) : data(_data){}
int GetX() {return data;}
A() {}
private:
int data;
};
int main()
{
A a(5);
A b;
b = a;
cout << b.GetX() << endl;
return 0;
}
运行结果为 5. 这就是一个浅拷贝的过程。
如果对象中没有其他的资源(如:堆,文件,系统资源等),则深拷贝和浅拷贝没有什么区别,
但当对象中有这些资源时,例子:
#include <iostream>
using namespace std;
class A
{
public:
A(int _size) : size(_size){ data = new int[size]; } //假如其中有一段动态分配的内存
int Get_Val() {return *data;}
int *Get_Val_add() { return data; }
A() {}
~A(){delete[] data; data = NULL; } //析构时释放资源
private:
int *data;
int size;
};
int main()
{
A a(5);
A b(a);
//b = a;
cout << b.Get_Val() << endl;
return 0;
}
因为类A中的复制构造函数是编译器生成的,所以A b(a)执行一个浅拷贝过程,浅拷贝只是对象数据之间的简单赋值 (如:b.size = a.size, b.data = a.data)
这里b的指针data 和a的指针指向了堆上的同一块内存,a和b析构时,b先把其data指向的动态分配的内存释放了一次,而后a析构时又将这块已经释放过的内存再释放一次。
对同一块内存释放执行2次及2次以上的释放会造成内存泄露或者是程序crash!
就需要用
深拷贝
来解决这个问题:
深拷贝就是当拷贝对象中有对其他资源(如堆、文件、系统等)的引用时(引用可以是指针或引用)时,对象的另开辟一块新的资源,而不再对拷贝对象中有对其他资源的引用的指针或引用进行单纯的赋值。
#include <iostream>
using namespace std;
class A
{
public:
A(int _size) : size(_size){ data = new int[size]; } //假如其中有一段动态分配的内存
int Get_Val() {return *data;}
int *Get_Val_add() { return data; }
A() {}
A( const A& _A) : size(_A.size){ data = new int[size]; } //深拷贝
~A(){delete[] data; data = NULL; } //析构时释放资源
private:
int *data;
int size;
};
int main()
{
A a(5);
A b(a);
cout << b.Get_Val() << endl;
return 0;
}
总结:
深拷贝和浅拷贝的区别是在对象状态中包含其它对象的引用的时候,当拷贝一个对象时,如果需要拷贝这个对象引用的对象,则是深拷贝,否则是浅拷贝。