浅拷贝对于带有 char[] 的结构是否足够?

发布于 2024-08-20 15:17:05 字数 127 浏览 6 评论 0原文

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

我已经在 C++ 中尝试过了,它有效,但我只是想确认这种行为是否安全。

I have a structure containing character arrays with no any other member functions. I am doing assignment operation between two instances of these structures. If I'm not mistaken, it is doing shallow copy. Is shallow copy safe in this case?

I've tried this in C++ and it worked but I would just like to confirm if this behavior is safe.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

画▽骨i 2024-08-27 15:17:05

如果“浅复制”是指在分配包含数组的 struct 后,该数组将指向原始 struct 的数据,那么:它可以t。数组的每个元素都必须复制到新的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中,你不能分配给数组< /a>.鉴于:

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

data_copy = data;

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

If by "shallow copy", you mean that after assignment of a struct containing an array, the array would point to the original struct's data, then: it can't. Each element of the array has to be copied over to the new struct. "Shallow copy" comes into the picture if your struct has pointers. If it doesn't, you can't do a shallow copy.

When you assign a struct containing an array to some value, it cannot do a shallow copy, since that would mean assigning to an array, which is illegal. So the only copy you get is a deep copy.

Consider:

#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;
}

The above will print:

Hello
hello

If, on the other hand, your struct had a pointer, struct assignment will only copy pointers, which is "shallow copy":

#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;
}

The above will print:

hello
hello

In general, given struct T d1, d2;, d2 = d1; is equivalent to memcpy(&d2, &d1, sizeof d2);, but if the struct has padding, that may or may not be copied.

Edit: In C, you can't assign to arrays. Given:

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

data_copy = data;

is illegal. So, as I said above, if you have an array in a struct, assigning to the struct has to copy the data element-wise in the array. You don't get shallow copy in this case: it doesn't make any sense to apply the term "shallow copy" to a case like this.

别低头,皇冠会掉 2024-08-27 15:17:05

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

您是正确的,即使在数组上,它也会进行浅复制。 (我假设您没有相对于 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 不会改变任何语义,它对于 char 数组的工作原理相同,复制每个字符。这是我的代码中的 S::a 情况。

请注意,pap 是浅层复制的(与所有其他成员一样)。如果这些指针“拥有”它们指向的内存,那么它可能不安全。 (你的问题中的“安全”是模糊的,实际上取决于你的期望以及你如何处理事情。)

对于一个有趣的转折,请考虑 boost::shared_ptr 和 C++ 中的其他智能指针。尽管可以进行深复制,但它们可以进行浅复制,并且这仍然是安全的。

Assigning structs does a member-wise assignment, and for arrays this means assigning each item. (And this is done recursively for "multiple dimension" arrays, which are really just arrays of arrays.)

You are correct that it does a shallow copy, even on arrays. (I'm assuming that you have not overloaded op= with respect to C++; if you overload it you can do anything you want.)

Remember that a shallow copy means copying the value of something, while a deep copy means copying the value to which something points or refers. The value of an array is each item in it.

The difference between shallow and deep is most meaningful when you have a type that does indirection, such as a pointer. I find my answer the most helpful way to look at this issue, but you could also say "shallow" vs "deep" doesn't even apply to other types, and they are just "copied".

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];
}

That I used int above doesn't change anything of the semantics, it works identically for char arrays, copying each char. This is the S::a situation in my code.

Note that p and ap are copied shallowly (as is every other member). If those pointers "own" the memory to which they point, then it might not be safe. ("Safe" in your question is vague, and really depends on what you expect and how you handle things.)

For an interesting twist, consider boost::shared_ptr and other smart pointers in C++. They can be copied shallowly, even though a deep copy is possible, and this can still be safe.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文