C语言解释深拷贝与浅拷贝 深浅拷贝

本文通过示例代码详细解析了C语言中深拷贝与浅拷贝的区别及应用场景,重点介绍了当结构体包含指针时如何避免内存释放错误。

一、不同方式拷贝出现的问题

最主要出现的问题是,例如结构体当中有一个字符型指针,使用了浅拷贝
两个结构体的字符型指针 free 释放时会报重复释放堆错误,而深拷贝不会。

二、浅拷贝

typedef struct Student {
	int id;
	char *name;
}st;

void deepShallowCopy()
{
	st st1,st2;
	st1.id=1;
	st1.name=(char*)malloc(10);
	st2.name=(char*)malloc(10);
	strcpy(st1.name,"张三");
	
	st2=st1;//方法1 
	// memcpy(&st2,&st1,sizeof(st));//方法2 
	printf("st1: id:%d name:%s\n",st1.id,st1.name );
	printf("st2: id:%d name:%s\n",st2.id,st2.name );
	printf("&id:%u &name:%u\n", &st1.id,st1.name );
	printf("&id:%u &name:%u\n", &st2.id,st2.name );
	if(st1.name!=NULL)free(st1.name);
	if(st2.name!=NULL)free(st2.name);
}

注意看14与15行
无论是哪种方法,都是属于浅拷贝
看输出即可找到答案:

st1: id:1 name:张三
st2: id:1 name:张三
&id:151454624 &name:19251216
&id:151454608 &name:19251216
*** Error in `./template': double free or corruption (fasttop): 0x000000000125c010 ***
======= Backtrace: =========
...省略

我们看这个name的地址,通过浅拷贝,st1的name与st2的name指向的是同一块地址空间,因此在释放的时候,会出现多次释放的错误

三、深拷贝

typedef struct Student {
	int id;
	char *name;
}st;

void deepShallowCopy()
{
	st st1,st2;
	st1.id=1;
	st1.name=(char*)malloc(10);
	st2.name=(char*)malloc(10);
	strcpy(st1.name,"张三");
	
	memcpy(st2.name,st1.name,strlen(st1.name)+1);//方法1
	//strcpy(st2.name,st1.name); //方法2
	st2.id=st1.id;//id也需要单独拷贝
	printf("st1: id:%d name:%s\n",st1.id,st1.name );
	printf("st2: id:%d name:%s\n",st2.id,st2.name );
	printf("&id:%u &name:%u\n", &st1.id,st1.name );
	printf("&id:%u &name:%u\n", &st2.id,st2.name );
	if(st1.name!=NULL)free(st1.name);
	if(st2.name!=NULL)free(st2.name);
}

同样的看14与15行,不对整个结构体赋值,而是针对对应的字符串进行拷贝,这样的话st1与st2的name指向的地址是不同的,因此释放也不会出问题。
输出:

st1: id:1 name:张三
st2: id:1 name:张三
&id:1000489904 &name:31944720
&id:1000489888 &name:31944752

三、总结

深浅拷贝总的来说,如果结构体中有指针存在,整个结构体一起赋值就是浅拷贝;单个成员赋值就是深拷贝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ySh_ppp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值