C語言結構體成員賦值的深拷貝與淺拷貝詳解
淺拷貝
C語言中的淺拷貝是指在拷貝過程中,對於指針型成員變量隻拷貝指針本身,而不拷貝指針所指向的目標,它按字節復制的。我們分幾種情況舉例子來看一下。
結構體中不存在指針成員變量時
代碼如下:
#include <stdio.h> typedef struct { char name[64]; int age; }Member; int main(){ Member stu1 = { "LiMing", 18 }; Member stu2; stu2 = stu1; printf("%s,%d\n", stu2.name, stu2.age); system("pause"); return 0; }
運行如下:
結構體中存在指針成員變量時
代碼如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char *name; int age; }Member; int main() { Member Member1, Member2; Member1.name = malloc(sizeof(char) * 64); if (NULL == Member1.name) { printf("malloc failed\n"); } memset(Member1.name, 0, 64); //strcpy(Member1.name, "LiMing"); snprintf(Member1.name, 64, "LiMing"); Member1.age = 18; Member2 = Member1;/*拷貝*/ snprintf(Member2.name, 64, "LiXiaoYao"); Member2.age = 29; printf("%s, %d\n", Member1.name, Member1.age); if (NULL != Member1.name) { free(Member1.name); Member1.name = NULL; } system("pause"); return 0; }
運行如下:
從中我們看到,改變Member2的值,Member1的值也改變瞭,這說明一片空間被兩個不同的子對象共享瞭,改變一個對象的值另外一個也會隨之改變。
我們改變Member2寫法,申請內存的代碼如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { char *name; int age; }Member; int main() { Member Member1; Member1.name = malloc(sizeof(char) * 64); if (NULL == Member1.name) { printf("malloc failed\n"); } memset(Member1.name, 0, 64); //strcpy(Member1.name, "LiMing"); snprintf(Member1.name, 64, "LiMing"); Member1.age = 18; Member Member2; Member2.name = malloc(sizeof(char) * 64); if (NULL == Member2.name) { printf("malloc failed\n"); } memset(Member2.name, 0, 64); //strcpy(Member2.name, "LiMing"); snprintf(Member2.name, 64, "LiXiaoYao"); Member2.age = 29; Member1 = Member2; printf("%s, %d\n", Member2.name, Member2.age); if (NULL != Member1.name) { free(Member1.name); Member1.name = NULL; } if (NULL != Member2.name) { free(Member2.name); Member2.name = NULL; } system("pause"); return 0; }
運行如下:
從中我們看到,當數據成員中有指針時,兩個類中的兩個指針將指向同一個地址,當對象快結束時,會調用兩次free函數,此時Member2已經是野指針(圖中有X的錯誤標志),這個野指針指向的內存空間已經被釋放掉,再次釋放會報異常錯誤,要解決這個問題就要涉及到深拷貝瞭。
深拷貝
深拷貝除瞭拷貝其成員本身的值之外,還拷貝成員指向的動態內存區域內容,深拷貝會在堆內存中另外申請空間來儲存數據。
解決的思路是在釋放掉被賦值指針變量的舊指向內存時,重新對其開辟新內存,這種情況下兩個結構體中指針地址不同,但是指向的內容是一致的。代碼如下:
#include <stdio.h> #include <stdlib.h> typedef struct { char *name; int age; }Member; int main() { Member Member1; Member1.name = malloc(sizeof(char) * 64); if (NULL == Member1.name) { printf("malloc failed\n"); } memset(Member1.name, 0, 64); //strcpy(Member1.name, "LiMing"); snprintf(Member1.name, 64, "LiMing"); Member1.age = 18; Member Member2; Member2.name = malloc(sizeof(char) * 64); if (NULL == Member2.name) { printf("malloc failed\n"); } memset(Member2.name, 0, 64); //strcpy(Member2.name, "LiMing"); snprintf(Member2.name, 64, "LiXiaoYao"); Member2.age = 29; if (Member1.name != NULL) { free(Member1.name); Member1.name = NULL; } Member1.name = malloc(strlen(Member2.name) + 1); strcpy(Member1.name, Member2.name); printf("%s, %d\n", Member1.name, Member1.age); if (NULL != Member1.name) { free(Member1.name); Member1.name = NULL; } if (NULL != Member2.name) { free(Member2.name); Member2.name = NULL; } system("pause"); return 0; }
運行如下:
結論
使用C語言來說,深拷貝淺拷貝的概念我們不需要深究,在進行結構體拷貝的時候,結構體成員是非指針的話,那麼直接賦值是沒有任何問題的,建議使用這種方式,避免淺拷貝這類不易發現的錯誤產生。
如果成員有指針類型,我們就需要重寫拷貝函數,自己定義拷貝行為瞭,這一點我們需要尤為註意。
到此這篇關於C語言結構體成員賦值的深拷貝與淺拷貝詳解的文章就介紹到這瞭,更多相關C語言深拷貝 淺拷貝內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!