#include#include using namespace std;class DeepCopy{public: DeepCopy() { cout<<"invoke default constructor"< name = name; cout<<"invoke normal constructor"<
在C++中,对象实例在编译的过程中,就会为其在stack上分配内存,同时返回一个指向对应地址空间的reference。(ps:new 声明的空间会分配在heap上,必须delete,不然会耗尽内存”)。下面我们简单介绍一下拷贝运算与赋值运算的使用场景以及区别。
当对象在声明的时候马上进行初始化,则称为拷贝运算。如:
DeepCopy a("hello");
当对象在声明之后,进行赋值运算,称之为赋值运算。如:
DeepCopy b;
b=a;
此时由于没有重新定义赋值运算,所以调用了系统默认生成的赋值函数。该赋值运算的原理是默认只拷贝位于stack中的值,对于heap上的值不会进行拷贝,只会指向同一个空间。(浅拷贝)
Tip:这样做还有一个坏处,当调用析构函数时,会两次删除heap上同一块空间,这样会报错。
为了解决浅拷贝的问题,我们需要在进行赋值运算的时候,对heap空间的内容同样进行拷贝,为其分配一个单独的内存空间,解决方案是:赋值运算符重载(深拷贝)。
Tips:只有在用到new 分配heap上空间时才需要深度拷贝!同时重写拷贝构造函数与赋值函数,针对heap空间单独分配。
DeepCopy& operator =( DeepCopy& a) //注意:此处一定要返回对象的引用,否则返回后其值立即消失! { if(name!=NULL) //删除原heap分配的空间,如果有的话 delete name; int len=strlen(a.name); name=new char[len+1]; //分配新的heap空间 strcpy(name,a.name); return *this; } DeepCopy(char* name) { this-> name=new char[strlen(name)+1]; strcpy(name,name); cout<<"invoke normal constructor"<
如果类内部有指向heap空间的指针,请一定要使用引用传递值,而不是简单使用值传递参数。对比如下:
DeepCopy& operator =( DeepCopy& a)//注意:此处一定要返回对象的引用,否则返回后其值立即消失! { if(name!=NULL) //删除原heap分配的空间,如果有的话 delete name; int len=strlen(a.name); name=new char[len+1]; //分配新的heap空间 strcpy(name,a.name); return *this; } DeepCopy dc1("hello"); DeepCopy dc2; dc2=dc1;
调用赋值函数时所经历的过程:
释放原来对象的堆空间
重新申请对应的堆空间
拷贝源堆空间的值到当前堆空间
返回对象的引用
但是如果函数返回的是值而不是对象的引用时,这时候由于没有进行深度拷贝,在析构临时变量的时候会删除heap空间内的内容会报错。(这个地方还不是特别清楚,我会持续更新的)