首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

深拷贝与浅拷贝(C+)

区别

浅拷贝:简单的赋值拷贝 深拷贝:在堆区申请新的空间进行拷贝

示例

为方便理解,引入一段错误代码

#include

#include

using namespace std;

class Person

{

public:

Person()

{

cout

}

Person(int age,int height)

{

pAge = age;

pHeight = new int(height);//堆区

cout

}

~Person()

{

//析构代码主要用于释放堆区数据

if (pHeight != NULL)

{

delete pHeight;

pHeight = NULL;

}

cout

}

int pAge;

int *pHeight;

};

void test()

{

Person p1(18,160);

cout

cout

//如果p2利用编译器提供的拷贝构造函数,会做浅拷贝操作(逐字节拷贝)

Person p2(p1);//默认的拷贝构造,为浅拷贝

cout

cout

}

int main()

{

test();

system("pause");

}

上述代码可正常通过编译,但实际运行后会提示以下错误

输出结果为

可以看到虽然原对象没有拷贝构造函数,但p2依然可以正确输出结果,但执行p2的析构函数时程序报错,因此只有p1的析构函数调用输出

原理

如果原对象没有拷贝构造函数,编译器会自动生成浅拷贝操作,源码为:

Person(const Person &p)

{

//默认拷贝构造函数

pAge = p.pAge;

pHeight = p.pHeight;

}

不难理解,编译器做的就是把源对象内的成员值简单复制了过来 这会导致p2内的堆区成员与p1同源,也即是指向同一块堆区地址(pAge为局部变量,储存在栈区,由编译器自动分配释放) 如果在test函数中输出一下p1.pHeightp2.pHeight就会发现值是相同的

当test函数结束时,编译器会做两件事:

销毁p1,调用析构函数将堆区p1.pHeight释放

销毁p2,调用析构函数将堆区p2.pHeight释放

因为p2中pHeight与p1指向同一块堆区地址,当p1将此地址释放后,p2重复释放,导致程序程序报错

解决办法

为避免重复释放导致程序报错,就要使用深拷贝操作,可以手动定义Person的拷贝构造函数:

Person(const Person &p)

{

cout

pAge = p.pAge;

pHeight = int new (*p.pHeight);//为pHeight开辟另一块堆区地址

}

此时p2将会为pHeight重新申请堆区空间,只是值与p1相同 如果输出p1.pHeight与p2.pHeight就会发现两者地址不同

图示

为方便理解,另附两张图 浅拷贝:

深拷贝:

摘自https://cloud.tencent.com/developer/article/2141799

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230405A06MOY00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券