我有一個包含沒有任何其他成員函數的字符數組的結構。我正在做這些結構的兩個實例之間的賦值操作。如果我沒有弄錯,它正在做淺拷貝。在這種情況下淺拷貝是否安全?對於帶有char []的結構,淺拷貝是否足夠?
我已經在C++中嘗試了這一點,它的工作原理,但我只想確認此行爲是否安全。
我有一個包含沒有任何其他成員函數的字符數組的結構。我正在做這些結構的兩個實例之間的賦值操作。如果我沒有弄錯,它正在做淺拷貝。在這種情況下淺拷貝是否安全?對於帶有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中,你can't assign to arrays。鑑於:
int data[10] = { 0 };
int data_copy[10];
data_copy = data;
是非法的。所以,正如我上面所說,如果你有一個struct
中的數組,分配給結構必須在數組中複製數據元素。在這種情況下,您不會獲得淺拷貝:將「淺拷貝」一詞應用於這種情況沒有任何意義。
分配結構會進行成員分配,對於數組來說,這意味着分配每個項目。 (這是針對「多維」數組遞歸執行的,它們實際上只是數組的陣列。)
即使在數組上,它也會執行淺拷貝,這是正確的。 (我假設你沒有對C++重載op =;如果你超載了它,你可以做任何你想做的事。)
請記住,淺拷貝意味着複製某些東西的值,而深層複製意味着複製某些指向或指向的值。數組的值是其中的每個項目。
當你有一個不間斷的類型,比如一個指針時,淺和深之間的區別是最有意義的。我覺得我的答案是最有用的方法來看待這個問題,但你也可以說「淺」與「深」甚至不適用其他類型,他們只是「複製」。
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不會改變語義的任何東西,它的作用相同的字符數組,複製每個字符。這是我的代碼中的S ::情況。
注意p和AP較淺複製(如每隔一個成員)。如果這些指針「擁有」它們指向的內存,那麼它可能不安全。 (在你的問題中「安全」是模糊的,真的取決於你的期望和你如何處理事情。)
對於一個有趣的轉折,考慮boost :: shared_ptr和C++中的其他智能指針。儘管可以進行深層複製,但它們可以被淺拷貝,並且這仍然是安全的。
是的,我理解指針的情況,但我只是不確定數組。 – jasonline 2010-02-11 02:09:02
@jasonline:看我的編輯。你不能分配給C中的數組,所以如果你的結構有數組(沒有指針),你就不能得到淺拷貝。 – 2010-02-11 02:16:14
@Alok:正在輸入我的答案。當然,你是無法分配給數組的,但那不是重點。即使在數組上,淺拷貝也不是深拷貝。 – 2010-02-11 02:30:05