使用gcc编译并在32位架构上执行时,以下程序返回16个字节。我想知道它为什么返回,因为它既不使用长的双成员也不是在64位机器上运行,并且没有定义虚拟函数来获取额外的内存字节,并且在计算 double的大小时和 int 数据成员,结果大约12个字节。那么为什么这个16字节值?
class A {
public:
void* data;
};
void* operator new (size_t sz, A& obj) {
printf("Custom operator new called for %d bytes\n", sz);
return obj.data;
}
class foo {
public:
double a;
int x;
foo() { printf("foo constructor called (this=%p)\n", this); }
};
int main() {
A obj;
obj.data = malloc(sizeof(foo));
printf("Allocator data: %p\n", obj.data); // Allocator data: 0x4601a8
foo *f = new (obj) foo; // Custom operator new called for **16 bytes**
// foo constructor called (this=0x4601a8)
printf("foo allocated at %p\n", f); // foo allocated at 0x4601a8
}
答案 0 :(得分:4)
4
末尾添加 foo
个字节作为填充。这通常用于对齐目的 - double
与架构上的8
字节对齐,因此如果创建foo
s的数组,则填充字节保证成员{{ 1}}正确对齐。
在类型中,无法保证大小等于成员大小的总和。通常情况下,它不是。
有一些特殊的编译器相关标志可以防止添加填充字节,您可以查找它们。 (a
)
答案 1 :(得分:0)
结构对象中可能存在未命名的填充,称为Data_structure_alignment
在你的情况下,double对齐到8个字节,所以sizeof foo应该是8 * N,所以4bytes填充
答案 2 :(得分:0)
当我运行你的代码时,我发现了以下内容:
class A {
public:
void* data;
};
void* operator new (size_t sz, A& obj) {
printf("Custom operator new called for %d bytes\n", sz);
return obj.data;
}
class foo {
public:
double a;
int x;
foo() { printf("foo constructor called (this=%p)\n", this); }
};
int main() {
A obj;
obj.data = malloc(sizeof(foo));
printf("Allocator data: %p\n", obj.data); // Allocator data: 0x991d008
printf("size of obj: %d\n", sizeof(obj)); // size of obj: 4
printf("size of foo: %d\n",sizeof(foo)); // size of foo: 12
foo *f = new (obj) foo; // Custom operator new called for **12 bytes**
// foo constructor called (this=0x991d008)
printf("foo allocated at %p\n", f); // foo allocated at 0x991d008
}
我添加了两个额外的打印声明,此处foo
的大小为12. double
+ int
。
答案 3 :(得分:0)
答案 4 :(得分:0)
考虑data alignment。编译器在oder中对齐对象的数据以将它们存储在内存中,以便CPU可以在一次加载中获取它们 - 这仅适用于对齐的数据。这是硬件方面。