受理查德鲍威尔的这次cppcon谈话的启发,我创建了以下代码片段来愚弄:
#includeusing std::cout; using std::endl; struct erdos { void who() { cout << "erdos" << endl; } float f1; float f2; }; struct fermat : public erdos { float f3; }; struct fermat2 : public fermat { float f4; }; struct fermat3 : public fermat2 { float f5; }; int main(void) { erdos e; cout << "sizeof(e)" << sizeof(e) << endl; fermat f; cout << "sizeof(f)" << sizeof(f) << endl; fermat2 f2; cout << "sizeof(f2)" << sizeof(f2) << endl; fermat3 f3; cout << "sizeof(f3)" << sizeof(f3) << endl; cout << "sizeof(void*)" << sizeof(void*) << endl; cout << "sizeof(float)" << sizeof(float) << endl; return 0; }
哪个会打印:
sizeof(e)8 sizeof(f)12 sizeof(f2)16 sizeof(f3)20 sizeof(void*)8 sizeof(float)4
添加virtual
到who()
我之后得到这个
sizeof(e)16 sizeof(f)24 sizeof(f2)24 sizeof(f3)32 sizeof(void*)8 sizeof(float)4
现在,添加结构的大小void*
很简单,但为什么在虚拟情况下会出现这种填充(理查德在他的演讲中也提到过)而不是非虚拟情况?
sizeof(e)16 - 8 = 8 sizeof(f)24 - 8 = 16 but is in fact 12 (padding 4) sizeof(f2)24 - 8 = 16 matches sizeof(f3)32 - 8 = 24 but is in fact 20 (padding 4)
我在Ubuntu 14.04 64位上使用gcc 5.3.0和clang 3.7.1进行了测试
sizeof(void*)8
嗯,这是你的答案.
假设您的实现只需要一个指针来处理虚拟查找,那就是对齐的原因.64位编译时,指针需要64位空间(这就是我们称之为"64位"的原因).但它也需要64位对齐.
因此,在64位编译中存储指针的任何数据结构也必须是64位对齐的.对象的对齐必须是8字节对齐,并且大小必须填充到8个字节(出于数组索引的原因).如果你让其中一个float
成员成为指针,你会看到同样的事情.