您的位置:首页 > 其它

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

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

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: