結構體中的淺拷貝與深拷貝
阿新 • • 發佈:2019-02-04
- 所謂淺拷貝就是編譯器機械的拷貝變數1中的內容到變數2中,如果是指標變數只會拷貝指標變數中存放的地址並不會拷貝指標所指向的記憶體空間的內容
- 深拷貝需要自己實現拷貝指標所指向的記憶體空間的內容
- 程式設計時不知道淺拷貝與深拷貝的關係可能會出現一些很難發現的錯誤
淺拷貝
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct student
{
char name[32];
char *_name;
int age;
};
struct student *Creat_student(int count)
{
int i=0;
struct student *stutemp=(struct student *)malloc(count*sizeof(struct student ));
if(stutemp==NULL)
{
printf("分配記憶體失敗!!!\n");
return NULL;
}
for(i=0;i<count;i++)
{
memset(&stutemp[i],0,sizeof(struct student));
stutemp[i]._name=(char *)malloc(32);
memset(stutemp[i]._name,0,32);
}
return stutemp;
}
void free_student(struct student *stu)
{
if(stu==NULL)
{
printf("stu==NULL");
return ;
}
if(stu->_name!=NULL)
{
free(stu->_name);
}
free(stu);
}
int main()
{
int num=1;
struct student *Stu1=NULL;
struct student *Stu2=NULL;
Stu1=Creat_student(num);
Stu2=Creat_student(num);
Stu1->age=20;
strcpy(Stu1->name,"321");
strcpy(Stu1->_name,"123");
Stu2=Stu1;//等號操作編譯器會執行淺拷貝機械的拷貝變數Stu1中的內容到變數Stu2中
free_student(Stu1);
free_student(Stu2);
//因為是淺拷貝 這樣幹相當於把同一塊記憶體釋放兩遍程式會崩潰
return 0;
}
程式執行時直接崩潰,我們可以分析一下他的記憶體Stu1和Stu2是指標變數分配四個位元組在棧區,經過Creat_student(num)函式後指向堆區分配的記憶體,在Creat_student(num)函式中又為*_name分配了空間不難畫出記憶體圖
在執行Stu2=Stu1後編譯器並沒有將Stu1所指向的記憶體空間資料拷貝給Stu2,而是直接將Stu1中所存的地址拷貝給Stu2,導致Stu2指向Su1所指的記憶體空間釋放兩次自然會導致程式崩潰。
如果將Stu2=Stu1改為*Stu2=*Stu1,程式同樣會崩潰,這是因為Stu1->_name直接指向了Stu1->_name 所指向的記憶體
深拷貝
void deep_copy(struct student *stu1,struct student *stu2)//深拷貝
{
memcpy(stu1,stu2,sizeof(struct student ));//先執行淺拷貝拷貝資料
stu1->_name=(char *)malloc(32);
memcpy(stu1->_name,stu2->_name,32);
}
深拷貝只需將Stu1=Stu2;改為deep_copy(Stu2,Stu1);這樣相當於手工給他拷貝了指標所指向記憶體空間的值,程式可以正常執行。