由于空类的大小是1个字节但是这个空类实际上是继承的(在gcc编译器上)sizeof(derived1)
的答案是8字节......,为什么会发生这种情况因为sizeof(derived1)
必须是sizeof(char)+sizeof(virtual pointer)
,这是1 + 4..ie 5字节。所以,从这个额外的3个字节到来的地方...... ???
#include <iostream>
using namespace std;
class Empty
{};
class Derived1 : virtual public Empty<br>
{
char c;
};
int main()
{
cout << "sizeof(Empty) " << sizeof(Empty) << endl;
cout << "sizeof(Derived1) " << sizeof(Derived1) << endl;
return 0;
}
答案 0 :(得分:5)
就C ++标准而言,它都未指定, 但通常虚拟继承会添加一个或两个指针 反过来又施加了额外的对齐限制;的大小 具有虚拟继承或虚函数的类 几乎肯定必须是指针大小的倍数 (大多数系统都是4或8)。
答案 1 :(得分:2)
问题在于结构内存对齐。有关详细信息,请查看此atricle:http://en.wikipedia.org/wiki/Data_structure_alignment 正如您所看到的,内存填充取决于您的平台。
说明:
让我们尝试调试用于您班级的内存。 我们知道变量不是虚拟。这意味着没有vintrual表的记录来确定使用哪个变量。因此,除非您没有虚函数,否则编译器不需要创建虚函数表。 在我的机器上,虚函数表指针成员称为__vfptr。在调试时,除非添加虚函数,否则无法找到具有此名称的成员。这意味着您应该从计算中删除虚函数指针大小。 尝试运行以下代码并阅读注释以获取详细信息:
struct Empty
{
};
struct VirtualNotEmpty: public virtual Empty
{
char c;
};
struct VirtualNotEmptyEx: public virtual Empty
{
char c1;
char c2;
char c3;
char c4;
};
struct TrueVirtualNotEmpty: public virtual Empty
{
virtual void f() {}
char c;
};
void inspect_vne()
{
VirtualNotEmpty vne;
char* start_of_struct = (char*)(&vne);
char* end_of_struct = (char*)(&vne);
end_of_struct += sizeof(vne);
char* start_of_var = (char*)(&(vne.c));
printf("sizeof(VirtualNotEmpty): %d\n", sizeof(vne)); // 8 bytes
printf("Address of struct %p\n", start_of_struct);
printf("Lenght of struct %d\n", (int)(end_of_struct - start_of_struct)); // same as sizeof
printf("Address of var c %p\n", start_of_var);
printf("Diff from start: %d\n", (int)(start_of_var - start_of_struct)); // 4 bytes: 1 byte for struct and 3 bytes for padding
printf("Diff from end: %d\n", (int)(end_of_struct - start_of_var)); // 4 bytes: 1 byte for struct and 3 bytes for padding
// [st][pd][pd][pd] [ch][pd][pd][pd]
// st -- struct vt -- virtual table, pd -- padding byte ch -- char member variable
}
void inspect_tvne()
{
TrueVirtualNotEmpty vne;
char* start_of_struct = (char*)(&vne);
char* end_of_struct = (char*)(&vne);
end_of_struct += sizeof(vne);
char* start_of_var = (char*)(&(vne.c));
printf("sizeof(TrueVirtualNotEmpty): %d\n", sizeof(vne)); // 12
printf("Address of struct %p\n", start_of_struct);
printf("Lenght of struct %d\n", (int)(end_of_struct - start_of_struct)); // same as sizeof
printf("Address of var c %p\n", start_of_var);
printf("Diff from start: %d\n", (int)(start_of_var - start_of_struct)); // 8 bytes: 1 byte for struct + 3 bytes of struct padding + 4 bytes o vptr
printf("Diff from end: %d\n", (int)(end_of_struct - start_of_var)); // 4 bytes: 1 byte for member variable + 3 bytes for padding
// [st][pd][pd][pd] [vt][vt][vt][vt] [ch][pd][pd][pd]
// st -- struct vt -- virtual table, pd -- padding byte ch -- char member variable
// member variable TrueVirtualNotEmpty::c can't be packed at first byte, because of order of dectaled members __vptr is declared bevore
// TrueVirtualNotEmpty::c
}
int main(int, char**)
{
printf("Size of pointer %d", sizeof(int*)); // 4 on my machine
inspect_vne();
inspect_tvne();
printf("Size of VirtualNotEmptyEx %d\n", sizeof(VirtualNotEmptyEx)); // there is no need to create padding at
// end for c1-c4 chars because there is space to pack them
return 0;
}
正如您所看到的,我的机器上的结构大小应该可以被4分割。