Gcc 使用 memcpy 作为隐式复制赋值运算符,而不是成员复制

Gcc uses memcpy for implicit copy-assignment operator instead of member-wise copy

本文关键字:复制 赋值运算符 成员 memcpy 使用 Gcc      更新时间:2023-10-16

遵循 C++ 11 标准,我认为每当完成两个对象之间的赋值时,G++ 都会隐式使用成员级副本。令人惊讶的是,我注意到与标准相反,g++ 似乎调用了一个大小为对象实际大小的 memcpy。下面是我的意思的片段。

#include <stdio.h>
class Classe {
public:
    Classe(char m1 = 0, int m2 = 0) : membro1(m1), membro2(m2) {};
    void setMembro1(char m1)    {membro1 = m1;}
    void setMembro2(int m2)     {membro2 = m2;}
    char getMembro1() const     {return membro1;}
    int getMembro2() const      {return membro2;}
private:
    char membro1;
    int membro2;
};
Classe c;
void function() {
    c = Classe('a', 1);
}
int main() {
    char ciao[] = "HELLO!";
    printf("Ciaon");
    function();
    printf("%dn", sizeof(Classe));
}

在执行结束时,我希望"c"对象所在的内存是{0x61,0x00,0x00,0x00,0x01,0x00,0x00,0x00},但显然,在第一个位置(包含0x61(旁边,"函数"函数数据的一些堆栈实际上被复制了,这是不正确的,恕我直言。

你知道发生了什么吗?非常感谢您的努力。

C++编译器

可以以它想要的任何方式实现成员的复制,只要结果符合C++规范。

在这种情况下,成员只是基本类型,并且底层架构不会妨碍,您的C++编译器可以很好地使用 memcpy(( 来执行复制。

在许多实现中,内存布局中char membro1和对象中的char membro2成员之间会有填充。

您在特定实现上看到的内存布局将意味着如下所示:

{0x61, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}
 |     |      |     |     |__________________|
 |     padding|     |              |
 |           padding|            membro2
membro1            padding

这 3 个填充字节中的内存内容没有指定,因此就C++而言,您以某种方式观察到的任何值都无关紧要 - 即使特定实现碰巧从堆栈中复制了该填充区域中的某些值。