Gcc 使用 memcpy 作为隐式复制赋值运算符而不是成员复制
Gcc uses memcpy for implicit copy-assignment operator instead of member-wise copy
遵循 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("Ciao\n");
function();
printf("%d\n", sizeof(Classe));
}
执行结束时我预计"c"对象所在的内存是{0x61, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},但显然,旁边第一个位置(包含 0x61),"function" 函数数据的一些堆栈实际上被复制过来,这是不正确的,恕我直言。
你知道发生了什么事吗?
非常感谢您的努力。
只要结果符合 C++ 规范,C++ 编译器就可以以任何方式实现成员的复制。
在这种情况下,成员只是基本类型,并且底层架构不会妨碍您,您的 C++ 编译器可以很好地使用 memcpy() 来执行复制。
在许多实现中,对象中 char membro1
和 char membro2
成员之间的内存布局中会有 padding。
您在特定实现中看到的内存布局将表示如下:
{0x61, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}
| | | | |__________________|
| padding| | |
| padding| membro2
membro1 padding
未指定这 3 个填充字节中的内存内容,因此就 C++ 而言,您以某种方式观察到的任何值都没有影响 - 即使特定实现碰巧复制了其中的某些值堆栈中的填充区域。
遵循 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("Ciao\n");
function();
printf("%d\n", sizeof(Classe));
}
执行结束时我预计"c"对象所在的内存是{0x61, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00},但显然,旁边第一个位置(包含 0x61),"function" 函数数据的一些堆栈实际上被复制过来,这是不正确的,恕我直言。
你知道发生了什么事吗? 非常感谢您的努力。
只要结果符合 C++ 规范,C++ 编译器就可以以任何方式实现成员的复制。
在这种情况下,成员只是基本类型,并且底层架构不会妨碍您,您的 C++ 编译器可以很好地使用 memcpy() 来执行复制。
在许多实现中,对象中 char membro1
和 char membro2
成员之间的内存布局中会有 padding。
您在特定实现中看到的内存布局将表示如下:
{0x61, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00}
| | | | |__________________|
| padding| | |
| padding| membro2
membro1 padding
未指定这 3 个填充字节中的内存内容,因此就 C++ 而言,您以某种方式观察到的任何值都没有影响 - 即使特定实现碰巧复制了其中的某些值堆栈中的填充区域。