news 2026/6/10 14:34:30

《你真的了解C++吗》No.017:零大小对象与空基类优化——消失的字节

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《你真的了解C++吗》No.017:零大小对象与空基类优化——消失的字节

《你真的了解C++吗》No.017:零大小对象与空基类优化——消失的字节

导言:虚无的重量

在直觉上,一个没有任何数据成员、没有虚函数的空类(Empty Class),其大小应该是0。然而,如果你在 C++ 中执行sizeof(EmptyClass),你会惊讶地发现结果通常是1

为什么“空”也有重量?这 1 个字节是从哪儿来的?而在继承体系中,这个字节又是如何神秘“消失”的?本章将带你揭开空基类优化(EBO)的秘密。


一、 为什么空类的大小不是 0?

C++ 标准规定:任何独立(Standalone)对象的大小至少为 1 字节。

理由很简单:为了确保同一个类的不同对象在内存中拥有唯一的地址。

想象一下,如果空类的大小是 0:

classEmpty{};Empty a,b;if(&a==&b){/* 它们是同一个对象吗? */}

如果大小为 0,ab的地址就会重叠。当你在数组中存放这些对象时,ptr++将永远停留在原地。为了让new返回唯一的指针,编译器必须为每个空类对象安插一个“占位符”字节。


二、 空基类优化(EBO / EBCO):空间的魔术

虽然独立对象不能是 0 字节,但当一个类作为基类存在时,情况就不同了。

空基类优化(Empty Base Optimization)允许派生类在继承空基类时,不为那个占位符字节分配空间。

1. 物理布局的对比
  • 非优化情况(组合关系)
    如果你在一个类里包含一个空类成员,编译器为了保证成员地址唯一,必须保留那 1 字节(由于内存对齐,甚至可能膨胀到 4 或 8 字节)。
  • 优化情况(继承关系)
    如果你继承自一个空类,编译器会认为基类只是提供了一个“接口”或“类型标签”,它不需要独立的地址。
classEmpty{};// 大小 1// 情况 A:组合 (Composition)classHolder{Empty e;// 占用 1 字节inta;// 占用 4 字节};// sizeof(Holder) 通常是 8 (由于对齐)// 情况 B:继承 (Inheritance) - 触发 EBOclassDerived:publicEmpty{inta;// 占用 4 字节};// sizeof(Derived) 通常是 4!那个 1 字节消失了。

三、 为什么 EBO 在底层开发中如此重要?

你可能会觉得,省下 1 到 4 个字节有什么大不了的?但在泛型编程(如 STL)中,EBO 是极致性能的关键。

典型应用:std::vector的分配器
std::vector通常持有一个分配器对象(Allocator)。大多数分配器是没有任何状态的空类。

  • 如果vector使用组合方式持有分配器,每个vector对象都会白白增大若干字节。
  • 如果vector的内部实现巧妙地继承自分配器,利用 EBO,分配器的空间开销就变成了0

四、 EBO 失效的时刻

EBO 并不是万能的。有一种情况会导致它失效:当派生类的第一个非静态成员变量的类型,恰好也是这个空基类时。

classEmpty{};classBogus:publicEmpty{Empty e;// 第一个成员也是 Emptyinta;};

为了保证基类Empty的地址和成员e的地址不同,编译器此时必须为基类分配空间。在这种布局下,sizeof(Bogus)会再次变大。


五、 C++20 的新方案:[[no_unique_address]]

在 C++20 之前,为了利用 EBO,开发者不得不强行使用“继承”来代替“组合”,这破坏了对象设计的语义(有时明明不是 Is-a 关系,却要写成继承)。

C++20 引入了属性标签,让组合也能享受 EBO:

structHolder{[[no_unique_address]]Empty e;// 告诉编译器:如果不必要,别给它分配地址inta;};// sizeof(Holder) 为 4

总结:空间的艺术

  • 独立空类:必须占 1 字节,以保证地址唯一。
  • 空基类:可以被优化为 0 字节,只要不产生地址冲突。
  • EBO是 C++ 程序员在不破坏抽象的前提下,压榨内存空间的优雅手段。

下一篇预告:聊完了空间的“消失”,我们要聊聊代码的“生成”。在 C++ 中,如果你不写某些函数,编译器会替你写;但它写出来的东西,真的是你想要的吗?

➡️《你真的了解C++吗》No.018:复制操作的隐式生成规则——“大三原则”的底层逻辑。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/22 2:08:36

计算机毕业设计springboot基于Java的美食网站系统 基于SpringBoot的Java美食分享与订餐一体化平台 融合在线商城的Java美食社区系统设计与实现

计算机毕业设计springboot基于Java的美食网站系统gv618t67 (配套有源码 程序 mysql数据库 论文) 本套源码可以在文本联xi,先看具体系统功能演示视频领取,可分享源码参考。“吃”是互联网永不过时的流量入口。当短视频把“看吃”推向高潮&…

作者头像 李华
网站建设 2026/6/5 23:42:34

DiffusionToolkit 终极指南:快速掌握AI图像元数据管理与智能检索

DiffusionToolkit 是一款专为AI生成图像设计的元数据索引器和可视化工具,能够帮助用户高效管理、检索和分析海量AI图像资源。无论你是AI艺术创作者、研究者还是数字内容资产管理师,这个开源工具都能显著提升你的工作效率。 【免费下载链接】DiffusionToo…

作者头像 李华
网站建设 2026/6/10 0:29:17

Luma3DS虚拟系统高阶配置指南:从原理到实战的深度优化

掌握Luma3DS虚拟系统(EmuNAND)的深度配置技巧,是每个3DS自制系统玩家进阶的必经之路。通过理解底层实现原理和掌握关键配置参数,你不仅能充分发挥虚拟系统的隔离保护优势,还能解锁更多高级功能。 【免费下载链接】Luma3DS Noob-proof (N)3DS …

作者头像 李华