結構體及其應用:結構體的深度拷貝,結構體內含指針

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


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章