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

三、总结

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

浅拷贝深拷贝是在C语言中常用的两种拷贝方式。 浅拷贝是指将原始数据的内存地址复制给目标对象,使得目标对象与原始对象指向同一块内存。这意味着当一个对象的数据发生改变时,另一个对象也会受到影响。浅拷贝通常使用memcpy函数来实现。 下面是一个使用浅拷贝的示例代码: ```c #include <stdio.h> #include <string.h> typedef struct { char name[20]; int age; } Person; int main() { Person person1; strcpy(person1.name, "John"); person1.age = 25; Person person2; memcpy(&person2, &person1, sizeof(Person)); printf("person1: %s, %d\n", person1.name, person1.age); printf("person2: %s, %d\n", person2.name, person2.age); strcpy(person2.name, "Mike"); person2.age = 30; printf("person1: %s, %d\n", person1.name, person1.age); printf("person2: %s, %d\n", person2.name, person2.age); return 0; } ``` 输出结果为: ``` person1: John, 25 person2: John, 25 person1: John, 25 person2: Mike, 30 ``` 可以看到,当修改person2的数据时,person1的数据也发生了改变。 深拷贝是指将原始数据完全复制一份到新的内存空间中,使得目标对象与原始对象互不影响。深拷贝通常需要手动分配内存,并逐个复制原始对象的成员变量。 下面是一个使用深拷贝的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char name[20]; int age; } Person; Person copyPerson(const Person* source) { Person dest; strcpy(dest.name, source->name); dest.age = source->age; return dest; } int main() { Person person1; strcpy(person1.name, "John"); person1.age = 25; Person person2 = copyPerson(&person1); printf("person1: %s, %d\n", person1.name, person1.age); printf("person2: %s, %d\n", person2.name, person2.age); strcpy(person2.name, "Mike"); person2.age = 30; printf("person1: %s, %d\n", person1.name, person1.age); printf("person2: %s, %d\n", person2.name, person2.age); return 0; } ``` 输出结果为: ``` person1: John, 25 person2: John, 25 person1: John, 25 person2: Mike, 30 ``` 可以看到,当修改person2的数据时,并不会影响person1的数据。这就是深拷贝的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

ySh_ppp

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

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

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

打赏作者

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

抵扣说明:

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

余额充值