空基类优化(EBCO)允许编译器对继承自空基类的派生类省略其存储空间,使sizeof(Derived)等于其非静态成员大小;需满足基类真正为空、无歧义继承路径且派生类有数据成员等条件。

空基类优化(Empty Base Class Optimization,EBCO)是C++编译器在对象内存布局中应用的一种标准允许的优化技术:当一个类继承自空基类(即不含非静态数据成员、无虚函数、无虚基类的类)时,编译器可以不为该空基类子对象单独分配存储空间,而是将其“折叠”进派生类的内存布局中——通常复用派生类的起始地址,从而避免内存浪费。
为什么需要EBCO?
没有EBCO时,即使空类(如struct Empty {})本身sizeof(Empty) == 1(满足对象地址唯一性要求),继承它也会带来额外字节填充。例如:
struct Empty {};
struct Derived : Empty { int x; }; // 若无EBCO,可能占用8字节(1+3填充+4)
实际中,主流编译器(GCC、Clang、MSVC)默认启用EBCO,所以上述Derived通常仅占4字节(int x直接位于对象起始处,空基类不占额外空间)。
EBCO生效的关键条件
不是所有空基类都能被优化。必须同时满足:
立即学习“C++免费学习笔记(深入)”;
- 基类类型真正为空:无非静态数据成员、无用户定义构造/析构/赋值函数(或这些函数均为默认/已删除)、无虚函数、无虚基类
- 该基类在继承链中不构成“歧义访问路径”(例如多重继承中两个相同空基类可能导致地址无法压缩)
- 派生类自身有数据成员(否则整个对象仍需至少1字节,但空基类仍可共享地址)
和空成员变量的区别
注意:EBCO只作用于空基类,不适用于空成员。比如:
struct Empty {};
struct BadExample {
Empty e; // 成员变量 → 占用1字节(不能省)
int x;
}; // sizeof(BadExample) 通常是8(1+3填充+4),无法跳过
而继承方式:
struct GoodExample : Empty {
int x; // EBCO生效 → sizeof(GoodExample) == 4
};
这是策略性设计差异:继承表达“is-a”,编译器可安全复用布局;成员表达“has-a”,语义上需独立存在地址。
实际影响与注意事项
EBCO虽透明,但在底层开发中不可忽视:
- 涉及reinterpret_cast或指针偏移计算时,不能假设空基类子对象地址一定等于派生类地址(尽管通常如此,但标准不保证)
- 使用std::is_empty可静态检查类型是否为空,辅助模板元编程判断是否可受益于EBCO
- 带状态的空类(如含静态成员或模板参数特化)仍算空类,不影响EBCO
- 禁用EBCO可通过编译器选项(如GCC的-fno-empty-bases),但极少需要
基本上就这些。EBCO是C++零开销抽象的典型体现——你不写额外代码,编译器就悄悄帮你省下每个字节。










