浅拷贝与深拷贝


C++中深拷贝与浅拷贝的不同 💖

1.浅拷贝😶‍🌫️

浅拷贝是指直接用系统提供的拷贝构造函数进行的简单赋值拷贝操作

2.深拷贝😶‍🌫️

深拷贝是指在堆区中重新申请空间,进行拷贝操作

3.代码示例🤯

构造一个Person类,其中构造函数可以发生函数重载:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Person {

public:
//普通构造函数
Person() {
cout << "这是普通构造函数调用" << endl;
}

//有参构造函数
Person(int age,int height) {
m_Age = age;
m_Height = new int(height); // 开辟一片堆空间
cout << "这是有参构造函数调用" << endl;
}

int m_Age;
int* m_Height;//创建身高指针,开辟到堆区
};

在其中添加析构函数,析构函数用于释放我们在堆区中开辟的空间:

1
2
3
4
5
6
7
8
~Person() {
//析构函数通常会将我们在堆区开辟的数据自动释放掉
if (m_Height != NULL) {
delete m_Height;
m_Height = NULL;
}
cout << "这是析构函数的调用" << endl;
}

这时候创建test01函数,用于检验我们的代码:

1
2
3
4
5
6
7
8
9
void test01() {                            //这时候没有拷贝构造函数
Person p1(18,160); //系统为我们自动提供拷贝构造函数

cout << "P1的年龄为: " << p1.m_Age << endl;

Person p2(p1);

cout << "P2的年龄为: " << p2.m_Age << endl;
}

在main中调用test01函数,发现程序出现错误

分析原因如下:

这是由于上面的代码,如果不写拷贝构造函数,系统自动提供一个拷贝构造函数把数据进行浅拷贝,系统在这时只会开辟一个堆空间,这时候进行析构函数的delete操作会多释放一个堆空间造成非法操作,因为多释放的堆区根本就不存在!

浅拷贝带来的问题:堆空间的重复释放,要利用深拷贝解决。

这时就要构造一个拷贝构造函数,进行深拷贝操作开辟两个堆空间,添加到class类中,代码如下:

1
2
3
4
5
6
7
8
Person(const Person &p) {
cout << "拷贝函数的调用" << endl;
m_Age = p.m_Age;
//m_Height = p.m_Height; 系统执行的就是这段代码,我们把它注释掉
//深拷贝操作:
m_Height = new int(*p.m_Height);

}

这样就完全解决了浅拷贝带来的指针重复指向同一堆区资源,执行释放代码delete时堆区资源重复释放的问题。

4.小结

C++中浅拷贝与深拷贝是容易混淆的点,但加以区分还是能很好辨认,故在编写代码时,要格外注意这一点。

请戳下面评论区,与我互相交流(需科学上网)


Author: Yui-Megumi
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint policy. If reproduced, please indicate source Yui-Megumi !
评论
  TOC