结构体及其应用:结构体的深度拷贝,结构体内含指针

来源:互联网 发布:java解析xml文件 编辑:程序博客网 时间:2024/05/22 22:22

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语言中我们只能不断提高自己的编程技巧来避免这样的问题的产生。

0 0
原创粉丝点击