news 2026/3/15 2:52:38

《你真的了解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/3/13 6:53:42

P2P直连工具终极指南:零基础实现远程主机直连

P2P直连工具终极指南:零基础实现远程主机直连 【免费下载链接】goodlink 全网最简单、零成本,一条命令将互联网任意两台主机直连!无中转、无安装、无注册。新增TUN模式,IP直连,不限端口 项目地址: https://gitcode.c…

作者头像 李华
网站建设 2026/3/12 23:44:04

终极指南:如何使用Martini框架快速构建Go Web应用

终极指南:如何使用Martini框架快速构建Go Web应用 【免费下载链接】martini Classy web framework for Go 项目地址: https://gitcode.com/gh_mirrors/ma/martini Martini是一款专为Go语言设计的优雅Web框架,以其简洁的语法和强大的功能而闻名。作…

作者头像 李华
网站建设 2026/3/13 16:30:00

Keil和Proteus联调方法详解:从原理到操作步骤

Keil与Proteus联调实战指南:零硬件也能高效开发单片机系统你是否曾因一块烧坏的STC89C52而耽误整个课程设计进度?是否在深夜调试串口通信时,反复插拔下载线却始终收不到正确数据?更别提实验室设备有限、学生排队等板子的尴尬场景。…

作者头像 李华
网站建设 2026/3/15 2:08:09

PyTorch安装教程GPU版太复杂?试试更稳定的TensorFlow-v2.9镜像方案

PyTorch安装教程GPU版太复杂?试试更稳定的TensorFlow-v2.9镜像方案 在深度学习项目的实际推进中,一个看似不起眼却频频卡住进度的环节——环境配置,往往成为开发者尤其是初学者的“第一道坎”。你是否也经历过这样的场景:满怀热情…

作者头像 李华
网站建设 2026/3/13 12:48:53

RISC-V架构下C语言性能极限优化,AI推理速度提升10倍的秘密

第一章:RISC-V架构下C语言性能极限优化,AI推理速度提升10倍的秘密 在RISC-V这一开源指令集架构的推动下,嵌入式与边缘计算领域的AI推理性能迎来了突破性进展。通过深度优化C语言实现,开发者能够在资源受限的RISC-V核心上实现高达1…

作者头像 李华
网站建设 2026/3/13 8:34:13

PaddleSpeech音频工具包:让语音AI开发像说话一样简单

PaddleSpeech音频工具包:让语音AI开发像说话一样简单 【免费下载链接】PaddleSpeech Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification Syste…

作者头像 李华