博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
C语言中结构体的深拷贝和浅拷贝
阅读量:5731 次
发布时间:2019-06-18

本文共 2670 字,大约阅读时间需要 8 分钟。

拷贝有两种:深拷贝,浅拷贝 

浅拷贝:拷贝过程中是按字节复制的,对于指针型成员变量只复制指针本身,而不复制指针所指向的目标

(1)结构体中不存在指针成员变量时

1 typedef struct { 2     char name[64]; 3     int age; 4 }Person; 5  6 void test005(){ 7  8     Person stu1 = { "aaa", 18 }; 9     Person stu2;10     stu2 = stu1;11     printf("%s,%d\n", stu2.name, stu2.age);12 }13 14 int main(){15     test005();16     system("pause");17     return 0;18 }

(2)结构体中存在指针成员变量时

1 typedef struct{ 2     char *name; 3     int age; 4 } Tea; 5  6 void test006(){ 7     Tea teacher1, teacher2; 8     teacher1.name = malloc(sizeof(char)* 64); 9     memset(teacher1.name, 0, 64);10     strcpy(teacher1.name, "aaaa");11     teacher1.age = 18;12 13 14     teacher2.name = malloc(sizeof(char)* 128);15     memset(teacher2.name, 0, 128);16     strcpy(teacher2.name, "bbbb");17     teacher2.age = 20;18 19     //结构体赋值20     teacher1 = teacher2;21 22     printf("%s, %d\n", teacher2.name, teacher2.age);23 24     if (NULL != teacher1.name){25         free(teacher1.name);26         teacher1.name = NULL;27     }28     if (NULL != teacher2.name){29         free(teacher2.name);30         teacher2.name = NULL;31     }32 }33 34 int main(){35     test006();36     system("pause");37     return 0;38 }

运行该结构体赋值,出现报错:

浅拷贝存在的问题:当出现类的等号赋值时,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的。但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次free函数,此时teacher2已经是野指针,指向的内存空间已经被释放掉,再次free会报错;另外,一片空间被两个不同的子对象共享了,只要其中的一个子对象改变了其中的值,那另一个对象的值也跟着改变了所以,这时,必须采用深拷贝。

深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。 

(3)上述代码的改进

 解决办法:释放掉被赋值指针变量的旧指向内存,重新对其开辟新内存存放,主要是为了使两个结构体中name指针地址不同,但是指向的内容一致。

1 void test006(){ 2     Tea teacher1, teacher2; 3     teacher1.name = malloc(sizeof(char)* 64); 4     memset(teacher1.name, 0, 64); 5     strcpy(teacher1.name, "aaaa"); 6     teacher1.age = 18; 7  8  9     teacher2.name = malloc(sizeof(char)* 128);10     memset(teacher2.name, 0, 128);11     strcpy(teacher2.name, "bbbb");12     teacher2.age = 20;13 14     //结构体赋值15     //teacher1 = teacher2;16     //-----------------------------------------------17     if (teacher1.name != NULL){18         free(teacher1.name);19         teacher1.name = NULL;20     }21     teacher1.name = malloc(strlen(teacher2.name) + 1);22     strcpy(teacher1.name, teacher2.name);23     //-----------------------------------------------24     printf("%s, %d\n", teacher1.name, teacher1.age);25 26     if (NULL != teacher1.name){27         free(teacher1.name);28         teacher1.name = NULL;29     }30     if (NULL != teacher2.name){31         free(teacher2.name);32         teacher2.name = NULL;33     }34 }

​建议:

我们在定义类或者结构体,这些结构的时候,最后都重写拷贝函数,避免浅拷贝这类不易发现但后果严重的错误产生

转载于:https://www.cnblogs.com/qinguoyi/p/10186219.html

你可能感兴趣的文章
MongoDB培训
查看>>
机器学习开源项目精选TOP30
查看>>
python基础===对字符串进行左右中对齐
查看>>
一起谈.NET技术,ASP.NET缓存全解析6:数据库缓存依赖
查看>>
代码分析系列 内存执行过程
查看>>
iOS开发-邮件发送
查看>>
/etc/resolv.conf文件详解
查看>>
【转】VC的MFC中重绘函数的使用总结(整理)
查看>>
JQuery日记_5.13 Sizzle选择器(六)选择器的效率
查看>>
System.gc()与Object.finalize()的区别
查看>>
Memcache存储大数据的问题
查看>>
HTML5区域范围文本框实例页面
查看>>
oracle查看经常使用的系统信息
查看>>
ifconfig命令
查看>>
mysql日常命令二
查看>>
函数的创建及使用时的注意事项
查看>>
解决安装SQL Server 2000提示文件挂起的一般方法
查看>>
tomcat的一个常见错误
查看>>
运维经验分享(五)-- 改进的java进程管理的服务控制脚本
查看>>
Linux C程序设计
查看>>