簡體   English   中英

淺層副本是否足夠用於具有char []的結構?

[英]Is shallow copy sufficient for structures with char[]?

我有一個包含字符數組的結構,沒有任何其他成員函數。 我正在這些結構的兩個實例之間進行賦值操作。 如果我沒有弄錯的話,它正在做淺拷貝。 在這種情況下,淺拷貝安全嗎?

我在C ++中嘗試了這個並且它有效,但我想確認這種行為是否安全。

如果通過“淺拷貝”,你的意思是在分配包含數組的struct后,數組將指向原始struct的數據,然后:它不能。 必須將數組的每個元素復制到新struct 如果您的結構有指針,“淺拷貝”會出現在圖片中。 如果沒有, 則不能進行淺層復制。

當您將包含數組的struct分配給某個值時,它不能執行淺表復制,因為這意味着分配給數組,這是非法的。 因此,您獲得的唯一副本是深層復制。

考慮:

#include <stdio.h>

struct data {
    char message[6];
};

int main(void)
{
    struct data d1 = { "Hello" };
    struct data d2 = d1; /* struct assignment, (almost) equivalent to
                            memcpy(&d2, &d1, sizeof d2) */

    /* Note that it's illegal to say d2.message = d1.message */

    d2.message[0] = 'h';
    printf("%s\n", d1.message);
    printf("%s\n", d2.message);
    return 0;
}

以上將打印:

Hello
hello

另一方面,如果你的struct有一個指針, struct賦值只會復制指針,這是“淺拷貝”:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct data {
    char *message;
};

int main(void)
{
    struct data d1, d2;
    char *str = malloc(6);
    if (str == NULL) {
        return 1;
    }
    strcpy(str, "Hello");
    d1.message = str;
    d2 = d1;

    d2.message[0] = 'h';
    printf("%s\n", d1.message);
    printf("%s\n", d2.message);
    free(str);
    return 0;
}

以上將打印:

hello
hello

一般來說,給定struct T d1, d2; d2 = d1; 相當於memcpy(&d2, &d1, sizeof d2); ,但如果結構有填充,可能會或可能不會被復制。

編輯 :在C中,您無法分配給數組 鑒於:

int data[10] = { 0 };
int data_copy[10];

data_copy = data;

是非法的。 因此,正如我上面所說,如果在struct有一個數組,則分配給結構必須在數組中按元素方式復制數據。 在這種情況下,您不會得到淺層副本:將“淺層副本”一詞應用於此類案例沒有任何意義。

分配結構執行成員分配,對於數組,這意味着分配每個項目。 (這是針對“多維”數組遞歸完成的,這些數組實際上只是數組的數組。)

你是正確的,它做一個淺拷貝,甚至在數組上。 (我假設你沒有重載op =關於C ++;如果你超載它你可以做你想做的任何事。)

請記住,淺拷貝意味着復制某些東西的值,而深拷貝則意味着復制某些東西指向或引用的值。 數組的值是其中的每個項目。

當你有一個間接的類型,例如指針時,淺和深之間的區別是最有意義的。 我發現我的答案是看待這個問題的最有用的方法,但你也可以說“淺”和“深” 甚至不適用於其他類型,它們只是“復制”。

struct S {
  int n;
  int* p;
  int a[2];
  int* ap[2];
  int xy[2][2];
};

void f() {
  S c, d;

  c = d;
  // equivalent to:
  c.n = d.n;
  c.p = d.p;

  c.a[0] = d.a[0];  // S::a is similar to your situation, only using
  c.a[1] = d.a[1];  // int instead of char.

  c.ap[0] = d.ap[0];
  c.ap[1] = d.ap[1];
  c.xy[0][0] = d.xy[0][0];
  c.xy[0][1] = d.xy[0][1];
  c.xy[1][0] = d.xy[1][0];
  c.xy[1][1] = d.xy[1][1];
}

我在上面使用int並沒有改變任何語義,它對char數組的工作方式相同,復制每個char。 這是我的代碼中的S :: a情況。

請注意, pap被淺層復制(與其他所有成員一樣)。 如果這些指針“擁有”它們指向的內存,那么它可能不安全。 (你問題中的“安全”是模糊的,實際上取決於你的期望和處理方式。)

有趣的是,請考慮使用C ++中的boost :: shared_ptr和其他智能指針。 它們可以被淺層復制,即使可以進行深層復制,這仍然是安全的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM