C++八股文 | 空类到底能不能实例化?那神奇的1字节藏着大秘密
面试官甩出一个类: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_type、std::false_type) -
策略类:作为模板参数实现编译期多态(如
std::unique_ptr的删除器有时就用空类) -
占位符:将来要填充数据或功能的临时结构
🎯 面试回答小模板
当被问“空类能不能实例化”,你可以这样输出层次感:
-
“可以实例化,语法完全合法。”
-
“实例占用至少 1 字节,用于保证每个对象有独一无二的地址,符合 C++ 对象模型。”
-
“编译器会为空类自动合成构造、析构、拷贝、移动等特殊成员函数。”
-
“独立对象占 1 字节,但作为基类时可启用空基类优化,基类部分不占额外空间。”
-
“常用于标记类型、策略模式、模板元编程。”
💡 记住一句话:空类不空,编译器给它埋了骨架;1 字节也不是真数据,只是地址的占位符。
需要完整《C++八股文》的小伙伴,可以点击下方传送门
>>2026版C++八股文<<
更多推荐


所有评论(0)