c++ - 为什么具有虚函数的类与没有虚函数的类对齐方式不同?

标签 c++ virtual-functions memory-alignment memory-layout vptr

受此启发cppcon talk by Richard Powell我创建了以下代码片段来愚弄:

#include <iostream>
using 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* 的大小添加到结构中很简单,但为什么在虚拟情况下而不是在非虚拟情况下会有这种填充(Richard 在他的演讲中也提到了这一点)案例?

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 成员设为指针,您会看到同样的结果。

关于c++ - 为什么具有虚函数的类与没有虚函数的类对齐方式不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34343506/

相关文章:

c++ - 读取 graphviz 的点文件而不在 boost 图中存储节点 ID

c++ - 为什么 temp->next!=NULL 有效而 temp!=NULL 在 C++ 的链表中不起作用

c++ - 为虚拟方法实现组合行为

types - 向 MPI 结构添加填充

c - 为什么编译器将此变量初始化为错误的值?这是对齐问题吗?

c++ - 如何在 Lua 中手动销毁包装的 C++ 类

c++ - C++中tstring到string的转换

c++ - 类虚拟成员函数中的线程

c++ - 在构造函数中调用虚函数

C++ 编译器对齐 - 仅字符无填充