64位程序下类与结构体的内存对齐差异:VS与GCC对比及标准疑问
问题解答
问题1:跨编译器下类B的sizeof差异成因及C++标准规定
差异成因
- Visual Studio(MSVC):64位环境下,默认对包含虚函数的类采用8字节对齐。类A包含8字节虚表指针(vptr)和4字节int成员
a,总长度12字节,需对齐到8的倍数,因此sizeof(A)=16;派生类B继承A后新增4字节int成员b,总长度16+4=20字节,再次对齐到8的倍数,最终sizeof(B)=24。 - GCC:遵循自然对齐规则,类的对齐边界取成员中最大的对齐要求(此处vptr为8字节,int为4字节,最大为8)。GCC会紧凑布局类成员:B的内存布局为8字节vptr + 4字节
a+ 4字节b,总长度16字节,刚好是8的倍数,无需额外填充,因此sizeof(B)=16。
C++标准的相关规定
C++标准并未强制统一内存对齐规则,仅做以下约束:
- 结构体/类的总大小必须是其对齐边界的整数倍,确保数组中元素能正确对齐。
- 类中每个成员的内存偏移量必须是自身对齐要求的整数倍。
- 仅规定虚函数的调用机制,不对虚表指针的具体布局、类的内存填充细节做强制要求。
因此,不同编译器可根据平台特性、编译选项自主选择对齐策略,这是跨编译器出现大小差异的核心原因。
问题2:VS下结构体C与类B对齐规则不同的原因
Visual Studio中,对齐规则会根据类型是否具备多态特性区分:
- 对于普通结构体(无虚函数、无继承自多态类),默认采用4字节对齐。结构体C的布局为:1字节char
a+ 3字节填充(对齐到int的4字节要求) + 4字节intb+ 1字节charc+ 3字节填充(对齐到结构体的4字节边界),总大小12字节,符合4字节对齐结果。 - 对于包含虚函数的类(或继承自多态类),默认采用指针大小的对齐(64位环境下为8字节),以此优化多态对象的访问效率,这就是类B采用8字节对齐的原因。
内容的提问来源于stack exchange,提问作者Zhang
相关产品推荐
相关产品推荐

