繁体   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