C++ 对于具有char[]的结构,浅拷贝是否足够?

C++ 对于具有char[]的结构,浅拷贝是否足够?,c++,c,struct,shallow-copy,C++,C,Struct,Shallow Copy,我有一个包含字符数组的结构,没有任何其他成员函数。我正在这些结构的两个实例之间执行赋值操作。如果我没弄错的话,这是在做肤浅的复制。在这种情况下,浅拷贝安全吗 我在C++中尝试过,它工作过,但是我想确认这个行为是否安全。 < P>如果用“浅拷贝”,你指的是在分配了包含数组的结构> 之后,数组会指向原始的代码>结构> 的数据,然后:它不能。数组的每个元素都必须复制到新的struct。如果你的结构有指针,“浅拷贝”就会出现。如果没有,你就不能做肤浅的复制 当您将包含数组的struct赋值给某个值时,它

我有一个包含字符数组的结构,没有任何其他成员函数。我正在这些结构的两个实例之间执行赋值操作。如果我没弄错的话,这是在做肤浅的复制。在这种情况下,浅拷贝安全吗

我在C++中尝试过,它工作过,但是我想确认这个行为是否安全。

< P>如果用“浅拷贝”,你指的是在分配了包含数组的<代码>结构> <代码>之后,数组会指向原始的代码>结构> <代码>的数据,然后:它不能。数组的每个元素都必须复制到新的
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;
}
另一方面,如果您的
struct
有一个指针,
struct
赋值将只复制指针,这是“浅复制”:

一般来说,给定
结构T d1,d2
d2=d1相当于
memcpy(&d2,&d1,d2的大小),但如果结构具有填充,则可能会复制,也可能不会复制

编辑:在C语言中,你可以。鉴于:


这是违法的。因此,正如我上面所说的,如果在
结构中有一个数组,那么分配给该结构必须在数组中复制数据元素。在这种情况下,您不会得到浅层复制:将术语“浅层复制”应用于这样的情况没有任何意义。

分配结构会进行成员分配,而对于数组,这意味着分配每个项。(这是针对“多维”数组递归完成的,它们实际上只是数组的数组。)

即使在阵列上,它也会进行浅拷贝,这是正确的。(我假设C++没有超载OP=;如果你超载它,你可以做任何你想做的事情) 记住,浅拷贝意味着复制某物的值,而深拷贝意味着复制某物指向或引用的值。数组的值是数组中的每个项

当您有一个执行间接寻址的类型(例如指针)时,浅层和深层之间的区别最有意义。我发现我的答案是看待这个问题最有帮助的方式,但你也可以说“浅”与“深”甚至不适用于其他类型,它们只是“复制”

我在上面使用int并没有改变任何语义,它对字符数组的作用是相同的,复制每个字符。这是代码中的S::a情况

请注意,p和ap的复制很浅(其他成员也是如此)。如果这些指针“拥有”它们指向的内存,那么它可能不安全。(“安全”在你的问题中是模糊的,实际上取决于你的期望和处理方式。)


一个有趣的转折点,考虑Booo::SydDypPTR和C++中的其他智能指针。即使可以进行深度复制,也可以进行浅层复制,这仍然是安全的。

是的,我理解指针的情况,但我不确定数组。@jasonline:请参阅我的编辑。你不能在C中分配数组,所以如果你的结构有数组(并且没有指针),你就不能得到一个浅层副本。@Alok:正在键入我的答案。当然,您是对的,您不能将其指定给数组,但这与问题无关。即使在数组上,浅拷贝也可以,而不是深拷贝。@Roger:好的,谢谢你的解释。我认为这是一个术语问题。我同意你的看法:如果结构的数组成员包含指针,指针值当然会被复制。我认为OP的意思是,如果assigned to struct的数组成员“指向”原始的“assignee”数组数据,答案是“不,它不能”。@Roger:鉴于OP在
结构中使用
字符
数组,我想我们可以通过“浅拷贝”来确定,他的意思是新的
struct
的数据将指向旧的
struct
的数据。
Hello
hello
#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
int data[10] = { 0 };
int data_copy[10];

data_copy = data;
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];
}