复制简单结构体时memcpy和'='的区别

Difference between memcpy and '=' when copying simple struct

本文关键字:区别 简单 结构体 memcpy 复制      更新时间:2023-10-16

考虑copy是一个简单的结构体,不需要特殊的复制语义。

struct A
{
    char i
    int i;
    long l;
    double b;
    //...maybe more member
}
struct A a;
a.c = 'a'; //skip other member just for illustrate
struct A b;
memset(&a, 0, sizeof(a));
b.c = a.c;
//...for other members, the first way to assign
memcpy(&b, &a, sizeof(b)); //the second way
b = a;    //the third way

这三种方法做同样的事情,似乎他们都是正确的。我曾经使用'memcpy'来复制简单的结构体,但现在看来'='也可以做同样的事情。那么使用memcpy和'='之间有什么区别吗?

memcpy将该结构视为一个连续的字节数组,并复制所有这些字节。因此,它将始终复制成员后的填充字节。

=只需要复制成员。它可能会也可能不会复制padding

我会养成使用=而不是memcpy的习惯。在C语言中,这种差异充其量是微乎其微的,但一旦你学会了c++,正如问题所示,这种差异是巨大的。例如

struct C {
  C() { }
  ~C() { } 
}
C local1;
C local2;
memcpy(&local2, &local1, sizeof(C));

在这种情况下,local2的构造函数在声明点运行。然而,该值的析构函数永远不会运行。相反,它的成员被神奇地替换为memcpy,析构函数在memcpy位上运行。如果C碰巧分配了任何资源,这很容易导致泄漏。

这三种方法中的任何一种——手动为每个成员赋值、为整个结构赋值或使用memcpy——都会导致b的所有成员与a的相应成员相同,这是您应该关心的。潜在的差异在于pad字节的值——memcpy会复制它们,不会给单个成员赋值,也可能不给整个结构赋值——这取决于实现。有些实现只使用memcpy来赋值结构,有些则逐个成员赋值,有些则根据结构体的大小等因素分别赋值。

我推荐使用结构赋值——它是最简单、最短和最面向问题的。将实现细节留给编译器。此外,在c++中,您可以自己定义赋值操作符以获得更大的控制和灵活性,并且memcpy是不受欢迎的,并且可能对类产生不良影响(参见JaredPar的回答)。