非多态C++类的大小为何大于其成员与基类的大小总和?
现象说明
你给出的测试代码如下:
struct A{}; struct B{}; struct C : A, B {}; struct D : A, B {}; struct E : C, D {}; int main() { static_assert(sizeof(C) == 1); static_assert(sizeof(D) == 1); //static_assert(sizeof(E) == 2); // Clang、GCC环境下成立 static_assert(sizeof(E) == 3); // MSVC环境下成立 }
所有编译器都遵循C++标准的基础要求:空类的大小至少为1字节,保证每个独立对象拥有唯一的内存地址,因此sizeof(C) == 1、sizeof(D) == 1是全平台通用的结果。
MSVC下sizeof(E) == 3的核心原因
这是MSVC空基类优化(EBCO)的特殊实现策略导致的:
- GCC、Clang的空基类优化规则更宽松:当派生类继承多个空基类时,只要基类类型不同,就允许基类子对象尽可能复用地址空间,因此E的两个基类C、D总共只占2字节,符合你预期的
sizeof(E) = sizeof(C) + sizeof(D)。 - MSVC的空基类优化有特殊限制:如果某一个空基类本身已经继承了其他空类(也就是示例中的C、D,都继承了A、B),那么当它作为更高层级派生类的基类时,MSVC不会将它的存储空间和同层级其他基类的存储空间复用,还会额外插入1字节的填充,确保所有层级的空基类子对象地址都唯一。最终E的大小就是
C的1字节 + 1字节填充 + D的1字节 = 3字节。
C++标准仅允许编译器实现空基类优化,没有强制要求优化的具体规则,因此MSVC的实现是符合标准要求的,只是和GCC/Clang的优化策略不同。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

