拷贝构造 和 拷贝赋值 函数:两个有本质区别,拷贝构造是拷贝类的某些属性然后在一个对象被创建时直接初始化赋值,拷贝复制是在创建完一个对象后,把另一对象的数据值复制过去覆盖掉。
举个简单例子:int a=3;是初始化 在定义一个变量a的时候,数据域直接把3填进去,而int a; a=3;是申请一个变量a。此变量有地址可能是0x1617,里面为NULL;a=3;的操作是覆盖掉原先的数据;即 NULL=3;
浅拷贝 与 深拷贝:默认拷贝构造函数为 浅拷贝,即只是简单的初始化赋值,平时我们自定义拷贝构造函数的时候对于简单数据处理都用的是浅拷贝,有一个很平常的类(以下通用)
class A {
private:
int a, b;
public:
A(){cin>>a>>b;}//构造函数
//这里有一个默认拷贝构造函数
};
常规操作
A a;
Ab(a);拷贝a对象初始化另一个对象b
但当我们数据成员初始化有”动态的变量“如为一个指针申请内存分配地址
class A {
private:
int a, b;
i int *p;
public:
A(){ //构造函数
cin>>a>>b;
p=new int (100);
}
//这里有一个默认拷贝构造函数
};
那么默认浅拷贝后的对象b里的动态数据成员地址会指向同一地址,而通常操作完之后,调用析构,我们要释放掉没用的空间。这时编译能通过,不会报错,但程序运行时会出错,原因时同一指针二次释放![{5`@H]EE0WQP@RX))``GWOB.png](https://upload-images.jianshu.io/upload_images/22662595-409cd2a9b58ab75b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
解决办法就是在自定义的拷贝构造里同样申请内存分配地址,然后把被拷贝对象成员里指针 p 存的数据值赋过去
A(const A& q)
{
a=q.a;
b=q.b;
p=new int (100);
*p=*(q.p);
}
当释放指针时,释放的是两块内存。