面试官甩出一个类:class Empty {}; 然后问“这玩意儿能实例化吗?”
你是不是愣住?今天带你看透空类的所有细节,从标准到编译器骚操作,一次讲透👇


1️⃣ 直接结论:可以!完全合法

空类没有任何成员变量、任何成员函数,但它仍然是一个完整的类型,完全可以创建对象。

class Empty {};
Empty e1;          // 合法
Empty e2;          // 合法
Empty* p = new Empty; // 合法

语法上没有任何限制,编译器必须支持。


2️⃣ 那它占多少内存?神秘的 1 字节

你用 sizeof(Empty) 会拿到 1,而不是 0。
为什么? C++ 标准有铁律:每个对象(最派生对象)必须拥有一个独一无二的地址。

如果空对象大小是 0,那么两个空对象就可以挤在同一个地址上,这会导致 &e1 == &e2,彻底破坏 C++ 的对象模型。所以标准规定,空类的完整对象至少要占 1 字节,用来“占个坑”,保证身份不同。

验证:

Empty a, b;
sizeof(Empty); // 1
&a != &b;      // true  (地址确实不同)


3️⃣ 这 1 字节里头有东西吗?

没有。 这 1 字节纯粹是编译器硬塞的“占位符”,里面不存任何有意义的数据,只是为了满足寻址要求。你不可以合法地读写它。


4️⃣ 编译器偷偷帮空类做了什么?(高频面试扩展)

就算你什么都不写,编译器也会自动给空类合成一大波特殊成员函数(需要用时才生成):

  • 默认构造函数 Empty()

  • 析构函数 ~Empty()

  • 拷贝构造函数 Empty(const Empty&)

  • 拷贝赋值运算符 Empty& operator=(const Empty&)

  • (C++11起) 移动构造函数 Empty(Empty&&)

  • (C++11起) 移动赋值运算符 Empty& operator=(Empty&&)

所以空类并不是真的“空”,背后是有完整骨架的,只是你看不见。


5️⃣ 进阶冷知识:空基类优化(EBO)

如果空类作为基类被继承,编译器通常会启用空基类优化,让基类子对象不额外占用派生类的空间,即基类部分大小为 0

class Empty {};
class Derived : public Empty {
    int x;
};
sizeof(Derived); // 通常为 4,不是 4+1=5

这是很多 STL(如 std::allocator)和策略类利用的技巧,省内存且符合标准。


6️⃣ 空类有什么用?

  • 标记类型:用于模板标签分发(如 std::true_typestd::false_type

  • 策略类:作为模板参数实现编译期多态(如 std::unique_ptr 的删除器有时就用空类)

  • 占位符:将来要填充数据或功能的临时结构


🎯 面试回答小模板

当被问“空类能不能实例化”,你可以这样输出层次感:

  1. “可以实例化,语法完全合法。”

  2. “实例占用至少 1 字节,用于保证每个对象有独一无二的地址,符合 C++ 对象模型。”

  3. “编译器会为空类自动合成构造、析构、拷贝、移动等特殊成员函数。”

  4. “独立对象占 1 字节,但作为基类时可启用空基类优化,基类部分不占额外空间。”

  5. “常用于标记类型、策略模式、模板元编程。”


💡 记住一句话:空类不空,编译器给它埋了骨架;1 字节也不是真数据,只是地址的占位符。

需要完整《C++八股文》的小伙伴,可以点击下方传送门

>>2026版C++八股文<<

更多推荐