继承空类A的类C仅含类B成员,为何sizeof(C)不等于sizeof(B)?
继承空类A的类C仅含类B成员,为何sizeof(C)不等于sizeof(B)?
这个问题其实戳中了C++里**空基类优化(Empty Base Optimization, EBO)**的一个关键限制,咱们一步步把它说透:
首先得先明白什么是空基类优化:空类(比如你的A)本身的sizeof是1字节——这是因为C++不允许对象的大小为0,编译器会给它加一个占位符字节。但当空类作为基类时,编译器可以把这个占位符优化掉,让子类的大小等于自身成员的大小。比如你的类B继承A后,sizeof(B)是4字节,就是因为EBO生效了:A的占位符被优化,只保留了int成员的4字节。
那问题出在类C身上:C同时做了两件事——继承空类A,又包含一个继承自A的类B的对象。这时候EBO的规则就不适用了,原因是:
- 类C自己作为A的子类,拥有一个属于自己的A基类子对象;
- 成员变量
a(类型B)本身也是A的子类,它内部也有一个属于自己的A基类子对象;
这两个A子对象是完全独立的,编译器没办法把它们的占位符合并优化——毕竟一个是C的基类部分,一个是成员B的基类部分,属于不同的对象实体。
接下来就是内存对齐的影响:在64位的GCC/Clang环境下,int类型的对齐要求是4字节。C的布局里,首先是自己的A基类子对象(本来1字节),为了满足后面成员B的对齐要求,这个1字节会被填充到4字节;然后加上成员B的4字节,总大小就变成了4+4=8字节。
你观察到的两种例外情况也能验证这个逻辑:
- 如果去掉C继承A,那C只包含B对象,此时C不需要处理自己的A基类部分,
sizeof(C)就等于sizeof(B)的4字节; - 如果去掉B继承A,那B就是普通的含int成员的类,C继承A时EBO可以正常生效(因为C的基类A和成员B之间没有共享空基类的冲突),所以
sizeof(C)也是4字节。
简单总结就是:当一个类同时持有同一个空基类的「基类子对象」和「成员子对象」时,编译器无法合并优化这两个空基类的占位符,再加上内存对齐的要求,最终导致C的大小比B多了4字节。
备注:内容来源于stack exchange,提问作者lei hu
相关产品推荐
相关产品推荐

