深拷贝与浅拷贝

构造函数会涉及到的拷贝函数:

拷贝函数中内存的释放

例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class person{
public:
person (int age,int height){
m_age = age;
m_height = new int (height);//有参函数的调用
}
//person(const person &p){//拷贝函数
//
//}
~person (){//析构函数:释放堆区中开辟的数据
if (m_height != NULL){
delete m_height;
m_height = NULL;
}
}


int m_age;
int *m_height;
}

void test (){
person p1 (18,160);

cout <<"p1的年龄为: "<<p1.m_age<<"p1的身高为: "<<*p1.m_height<<endl;

person p2(p1);

cout <<"p2的年龄为: "<<p2.m_age<<"p2的身高为: "<<*p2.m_height<<endl;
}

int main (){
test();
return 0;
}

**person p2(p1);**这里的拷贝属于编译器自己的浅拷贝;

他会把p1对应的m_age的值给p2对应的m_age;将p1的m_height 的地址拷贝给p2的m_height.

理想输出是:

p1的年龄为: 18 p1的身高为:160

p2的年龄为: 18 p2的身高为:160

但是在main函数运行的时候会崩


原因分析:

当调用test函数时,栈区中p1中申请了堆区数据m_height,按照编译器默认的浅拷贝再将m_height的地址传给了p2中的m_height。那么在test函数调用结束的时候按照栈的存储方式(先进后出)p2会先释放掉m_height,那么当p1释放的时候m_height已经被释放掉了,所以导致了程序崩。

解决方式

自己实现一个深拷贝函数,将p2的m_height内存指向另一个地址含有相同的值的地方,那么在内存释放的时候就不会矛盾。

深拷贝函数:

1
2
3
4
5
6
//深拷贝函数
person (const person &p){
m_age = p.m_age;
// m_height = p.m_height; // 这是编译器默认实现的浅拷贝
m_height = new int (*p.m_height);
}

如此便可以做到预期的结果。