空类的 sizeof 为 1 是因 c++ 标准要求每个对象必须有唯一地址,编译器插入一个 char 占位符;继承空基类时若满足条件可触发 ebo 使派生类大小仍为 1,但虚继承或重复继承会禁用 ebo;添加虚函数后需存储 vptr,x64 下大小变为 8;结构体中空类受对齐规则影响,实际大小需结合上下文判断。

空类的 sizeof 为什么是 1 而不是 0
因为 C++ 标准强制要求:任何对象在内存中必须有唯一地址,哪怕它不包含成员。如果空类大小为 0,那么两个同类型空对象就可能被分配到同一地址,违反“每个对象有独立地址”的前提。编译器为此悄悄插入一个 char 占位符,所以 sizeof 至少为 1。
继承空基类时 sizeof 可能还是 1 —— EBO 生效了
空基类优化(Empty Base Optimization, EBO)允许派生类不为继承的空基类额外分配空间。但前提是该空基类不参与虚继承、且不是最底层的多继承中重复出现的基类。
-
class Empty {};→sizeof(Empty)是 1 -
class Derived : Empty {};→sizeof(Derived)很可能仍是 1(EBO 生效) -
class A : virtual Empty {};→sizeof(A)通常 > 1(虚继承禁用 EBO) -
class B : Empty, Empty {};→ 编译错误(重复基类名),但若用不同空类,sizeof可能为 2(EBO 不跨基类生效)
加了虚函数后 sizeof 突然变大
一旦类声明虚函数(哪怕只有 virtual ~Empty() = default;),编译器就得塞入虚表指针(vptr)。这个指针大小取决于平台:x64 下通常是 8 字节,x86 下是 4 字节。此时空类不再“空”,占位符 + vptr 共同决定大小。
class EmptyV { virtual ~EmptyV() = default; };- x64 下
sizeof(EmptyV)是 8(vptr 占满,原char被合并或对齐覆盖) - 即使再加一个
int成员,只要对齐合适,sizeof可能仍为 8(例如int在前,vptr 在后,共 8 字节) - 注意:vptr 位置由 ABI 决定(通常在对象开头),不能假设偏移量
结构体对齐和空类嵌套让 sizeof 更难猜
空类本身大小是 1,但它在结构体中会受整体对齐规则影响。尤其当它与其它成员混排,或作为模板参数被实例化时,实际布局可能出人意料。
立即学习“C++免费学习笔记(深入)”;
-
struct S { char c; Empty e; };→sizeof(S)很可能是 2(c占 1 字节,e占 1 字节,无填充) -
struct T { double d; Empty e; };→sizeof(T)很可能是 16(d占 8 字节,对齐要求后续起始地址为 8 的倍数,e插入 7 字节填充 + 1 字节占位,共 16) - 模板元编程中用空类做标记类型(如
std::integral_constant)正是依赖 EBO 和小尺寸,但一旦加入constexpr静态成员或别名,可能意外破坏优化
真正容易被忽略的是:空类大小不是编译器“随意定的 1”,而是标准约束 + 对齐规则 + 优化策略三者博弈的结果;调试时看 sizeof 不能只盯类定义,得结合它在具体上下文中的使用方式。









