结构体及其应用:结构体的深度拷贝,结构体内含指针
2015-11-01 08:36
375 查看
1、在前一篇文章中提到,尽量不要使用赋值操作符来操作结构体,这其中所涉及的便是结构体的深度拷贝。
对于下面这个例子:struct teacher { char szName[24]; int age; double income; }
进行以下的操作:
struct t1,t2; strcpy(t1.szName,"Lucy"); t1.age =24; t1.income = 10789.4; t2=t1;
</pre><pre name="code" class="cpp" style="background-color: rgb(255, 255, 255);">
<pre name="code" class="cpp" style="background-color: rgb(255, 255, 255);">上述操作不会出现任何的问题,程序也会达到我们预期的目的。但是对于下面的例子呢:
<pre name="code" class="cpp">struct teacher { char *pName; int age; double income; }
我们进行如下的操作:
<pre name="code" class="cpp">struct teacher t1,t2; t1.pName = (char*)malloc(24*sizeof(char)); memset(t1.pName,0,24*sizeof(char)); strcpy(t1.pName,"Lily"); t1.age = 23; t1.income = 9877.4; t2 = t1;
乍看之下,似乎没有什么问题。但是这只是程序的一部分,在程序中进行了内存的分配,t1.pName = (char*)malloc(24*sizeof(char));
现在执行赋值运算符,使得t2和t1有相同的内容,此时t2.pName 和 t1.pName指向相同的内存空间。我们知道动态分配的内存需要通过free(C语言中)来释放掉,否则会出现内存泄露。
我们执行下面的操作:
if( NULL!= t1.pName) { free(t1.pName); t1.pName = NULL;//释放之后立即置空,防止出现悬垂指针 }
此时我们将给t1的pName分配的内存空间释放掉之后,t2.pName 便指向了一块不存在的内存空间,此时t2.pName 的行为便是未定义的,如果强行对t2.pName 进行操作,会引起程序的崩溃,那么我们该如何来操作呢?
2、结构体的深度拷贝
首先看一个例子:#include "stdlib.h" #include "stdio.h" #include "string.h" //结构体的定义 typedef struct _AdvTeacher { char *name; char buf[100]; int age; }Teacher ; Teacher * creatT() { Teacher *tmp = NULL; tmp = (Teacher *)malloc(sizeof(Teacher)); tmp->name = (char *)malloc(100); if (NULL == tmp->name) { printf("%s","内存分配失败!"); return NULL; } tmp->age = 23; strcpy_s(tmp->name, 100, "Lucy"); strcpy_s(tmp->buf, 100, "Huazhong University of science and technology"); return tmp; } void display_Teacher(Teacher *pTeacher) { if (NULL == pTeacher) { printf("%s", "NULL Object"); return; } printf("name:%s,age:%4d ,buf:%s", pTeacher->name, pTeacher->age, pTeacher->buf); printf_s("name::%s", pTeacher->name); printf("HelloWorld!"); } void FreeT(Teacher *t) { if (t == NULL) { return ; } if (t->name != NULL) { free(t->name); } } void copyObj(Teacher *to, Teacher *from) { //*to = *from;//copy; to->name = (char *)malloc(100); if (NULL == to->name) { printf("%s", "内存分配失败!"); return; } strcpy_s(to->name,200, from->name); to->age = from->age; strcpy_s(to->buf, 100, from->buf); } void mainError() { Teacher *t1; Teacher t2; t1 = creatT(); copyObj(&t2, t1); //printf_s("%s","t1 Content:"); display_Teacher(t1); //printf("\n%s", "t2 Content:"); display_Teacher(&t2); FreeT(t1); FreeT(&t2); // }
程序运行的结果如图所示
解释一下这个程序:
createT();函数来创建Teacher对象,并且在createT()内部分配内存空间。copyTeacher()用来执行深度拷贝,给t2.pName()分配内存空间,并且将t1中的内容拷贝给t2。
最后分配的内存空间通过freeT();来释放掉,避免内存泄露的发生。
所以我们一定要避免对结构体内部嵌套指针时使用赋值操作符,因为在C语言中没有提供操作符重载,所以我们不能给赋值操作符以新的含义,在C语言中我们只能不断提高自己的编程技巧来避免这样的问题的产生。
相关文章推荐
- 国家规划和个体愿景
- c#入门
- httpcore和httpclient的源码一点点(1)
- iphone开发中的一些小技巧
- ACdream 1196 KIDx's Pagination(模拟)
- 面向对象的概念详解(转)
- 前所未有的神速,仅半年后就推出了 GNU Hurd 0.7
- sersync服务实战
- 国家商用密码(八)在Apache MINA上实现文本流的SM4编解码器
- 老中医传授6步护肝秘诀
- java中g.drawImage(pict, a, b, 50, 50, this);函数出错问题
- Java记录 -48- Java数据结构-链表
- [Linux学习笔记] Linux常用命令 - 帮助命令
- 适配器模式 -- 大话设计模式
- 国家商用密码(七)在Apache MINA上实现二进制流的SM4编解码器
- red hat使用
- 状态模式 -- 大话设计模式
- 抽象工厂模式 -- 大话设计模式
- 日常总结(九)Editplus和Notepad++设置默认编码
- (第二部分)容器和算法——顺序容器