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/15 20:09:42

如何将任意程序添加到 Windows 右键菜单?一文详解实现方案

无论工作还是学习,用户往往需要频繁调用某些应用程序。 若能将这些程序集成至系统右键菜单中,将显著提升操作效率。 “右键菜单管理工具”正是一款为此设计的实用软件,支持 .exe、.bat、.cmd、.ps1、.vbs、.py 等多种可执行文件及脚本格式。…

作者头像 李华
网站建设 2026/6/10 14:32:16

支持无限多开的酒店小程序源码系统,轻松服务多家客户

温馨提示:文末有资源获取方式详细功能列表:在线订房核心功能:支持多房型管理(如标准间、套房)、动态价格设置(包括旺季折扣)、实时库存更新,客户可以通过日历视图选择日期&#xff0…

作者头像 李华
网站建设 2026/6/10 14:54:23

如何用一套系统,搭建属于你自己的酒店预订平台?

温馨提示:文末有资源获取方式 酒店在线预订已成为标配,但你的商业眼光不应只局限于服务一家酒店。你是否想过,成为那个为众多酒店提供技术解决方案的平台搭建者?今天,我们将深入解析一款能让你实现此愿景的酒店在线订房…

作者头像 李华
网站建设 2026/6/10 15:30:30

基于vTaskDelay的电机控制时序操作指南

用好vTaskDelay,让电机控制不再“卡死”——一个嵌入式工程师的实战笔记你有没有遇到过这种情况:写了一个直流电机启停程序,主循环里加了个delay_ms(2000),结果期间按键没响应、串口收不到命令,连看门狗都差点拉不回来…

作者头像 李华
网站建设 2026/5/24 6:35:56

从零构建高效算子库,昇腾C语言开发必备的5种高阶编程模式

第一章:从零构建高效算子库——昇腾C语言开发概述在人工智能计算领域,昇腾(Ascend)AI处理器凭借其高算力密度和能效比,成为深度学习推理与训练任务的重要硬件平台。基于C语言的算子开发是充分发挥昇腾芯片性能的核心手…

作者头像 李华
网站建设 2026/6/10 16:26:30

15分钟快速上手:AI动画生成新手配置指南

15分钟快速上手:AI动画生成新手配置指南 【免费下载链接】StableAnimator [CVPR2025] We present StableAnimator, the first end-to-end ID-preserving video diffusion framework, which synthesizes high-quality videos without any post-processing, condition…

作者头像 李华