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)