首頁 > 軟體

C語言結構體成員賦值的深拷貝與淺拷貝詳解

2022-10-02 14:00:33

淺拷貝

C語言中的淺拷貝是指在拷貝過程中,對於指標型成員變數只拷貝指標本身,而不拷貝指標所指向的目標,它按位元組複製的。我們分幾種情況舉例子來看一下。

結構體中不存在指標成員變數時

程式碼如下:

#include <stdio.h>
typedef struct {
    char name[64];
    int age;
}Member;
 
int main(){
    Member stu1 = { "LiMing", 18 };
    Member stu2;
    stu2 = stu1;
    printf("%s,%dn", 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 failedn");
 }
 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, %dn", 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 failedn");
 }
 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 failedn");
 }
 memset(Member2.name, 0, 64);
 //strcpy(Member2.name, "LiMing");
 snprintf(Member2.name, 64, "LiXiaoYao");
 Member2.age = 29;
 
 Member1 = Member2;
 
 printf("%s, %dn", 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 failedn");
 }
 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 failedn");
 }
 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, %dn", 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語言深拷貝 淺拷貝內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com