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語言中我們只能不斷提高自己的編程技巧來避免這樣的問題的產生。