C++ 为什么sizeof(基本)与sizeof(派生)没有区别

C++ 为什么sizeof(基本)与sizeof(派生)没有区别,c++,sizeof,virtual-functions,memory-layout,vptr,C++,Sizeof,Virtual Functions,Memory Layout,Vptr,我认为sizeof(Base)应该是12。为什么是16 没有虚函数,我得到4和8 类基{ 公众: int i; virtual void Print(){cout发生这种情况的原因是编译器决定对齐类 如果您希望(或需要)结构或类具有其“真实”大小,可以像这样使用#pragma pack(1): #pragma pack(push, 1) // Set packing to 1 byte and push old packing value to stack class Base{ publ

我认为
sizeof(Base)
应该是12。为什么是16

没有虚函数,我得到4和8

类基{
公众:
int i;

virtual void Print(){cout发生这种情况的原因是编译器决定对齐类

如果您希望(或需要)结构或类具有其“真实”大小,可以像这样使用
#pragma pack(1)

#pragma pack(push, 1) // Set packing to 1 byte and push old packing value to stack

class Base{
  public:
    int i;
    virtual void Print(){cout<<"Base Print";}
};

class Derived:public Base{
  public:
    int n;
    virtual void Print(){cout<<"Derived Print";}
};

int main(){
  Derived d;
  cout<<sizeof(Base)<<","<<sizeof(d);
  return 0;
}

#pragma pack(pop) // restore old packing value
#pragma pack(push,1)//将packing设置为1字节,并将旧的packing值推送到堆栈
阶级基础{
公众:
int i;
虚拟空打印(){cout
为什么sizeof(基本)与sizeof(派生)没有区别

因为编译器引入了对齐

这取决于体系结构,但为了简单起见,我假设我们指的是64位体系结构

类型
Base
的对齐方式为
8
字节:

alignOfBase(): # @alignOfBase()
  mov eax, 8
  ret
Base
的布局由变量成员(
int
)和虚拟表(
vtptr
)组成

如果我们假设一个“通用”架构,其中:

  • int
    是4字节大小
  • vtptr
    是一个指针。在64位体系结构上是8字节大小
正如您所期望的,我们应该有一个
4+8=12

但是,我们需要记住
Base
的对齐方式是
8字节
。因此,连续的
Base
类型应存储在8的倍数位置

为了保证这一点,编译器为
Base
引入了填充。这就是
Base
大小为16字节的原因

例如,如果考虑2个连续的<代码>基础<代码>(<代码> BASE0和<代码> BASE1),没有填充:

0:  vtptr (base 0) + 8
8:  int   (base 0) + 4
12: vtptr (base 1) + 8  <--- Wrong! The address 12 is not multiple of 8.
20: int   (base 1) + 4
事实上,在这种情况下,不需要引入填充来保持
派生的
与内存对齐。布局大小将与实际大小相同

0:   vtptr (Derived 0)
8:   int   (Derived 0)
12:  int   (Derived 0)
16:  vtptr (Derived 1)  <---- Fine. 16 is multiple of 8.
24:  int   (Derived 1)
28:  int   (Derived 1)
0:vtptr(派生0)
8:int(派生0)
12:int(派生0)

16:vtptr(派生1)可能是一个填充问题?请注意,除非您有非常充分的理由绕过对齐规则,否则您可能不应该这样做。谢谢,它确实帮助了我。注意,
#pragma pack
是一个编译器扩展。您忘了解释数组和结构之间的区别:
struct{t x1,x2;};
(原则上)可以有填充,但根据定义,
tx[2]
不能,因此数组中的任何对象(任何具体对象类型)都必须具有与其对齐方式兼容的大小。
alignOfDerived(): # @alignOfDerived()
  mov eax, 8
  ret
0:   vtptr (Derived 0)
8:   int   (Derived 0)
12:  int   (Derived 0)
16:  vtptr (Derived 1)  <---- Fine. 16 is multiple of 8.
24:  int   (Derived 1)
28:  int   (Derived 1)