【C/C++】EBO空基类优化介绍
空对象优化(Empty Base Optimization,简称 EBO)是 C++ 编译器的一种 优化技术,用于消除空类作为基类时占用的内存空间,从而避免浪费空间、提升结构体或类的存储效率。
1 什么是“空对象”?
一个**空类(empty class)**是指:
class Empty {};
它没有任何数据成员(包括虚函数、虚继承等),仅有默认的构造/析构函数。根据 C++ 的标准:
每个对象都必须具有唯一的地址,即使它不包含任何数据。
所以如果你直接定义:
Empty e1, e2;
编译器仍然会让 sizeof(Empty) >= 1
,通常为 1 字节,以保证地址唯一性。
2 空对象优化(EBO)原理
空类作为基类时,如果派生类没有其它成员使用其地址,那么可以省略它占用的空间。
示例:空对象优化前后对比
// 不继承空类:直接成员,浪费空间
class Empty {};struct NotOptimized {int x;Empty e;
};// 使用继承:可以应用 EBO
struct Optimized : Empty {int x;
};
对比 sizeof
:
std::cout << sizeof(NotOptimized) << "\n"; // 可能是 8(int + 空类占1 + padding)
std::cout << sizeof(Optimized) << "\n"; // 通常是 4(只包含 int)
结果说明:
NotOptimized
:包含一个Empty
成员,因此占用额外空间;Optimized
:Empty
作为基类,如果没有虚函数/虚继承,编译器可以完全消除其空间。
3 EBO 的典型应用场景
标准库容器优化
STL 中 std::function
、std::tuple
、std::optional
等结构都大量使用了 EBO。
template<typename T, typename Deleter = std::default_delete<T>>
class unique_ptr {T* ptr;Deleter deleter; // 如果 Deleter 是空类,会占额外空间
};
如果不优化,unique_ptr<int, EmptyDeleter>
也会占两个指针大小(ptr + deleter
),但 EBO 可以优化掉 deleter
空类的空间占用。
函数对象封装/策略模式
template<typename F>
struct FuncWrapper : F {void operator()() { F::operator()(); }
};
如果 F
是空类,比如一个无状态 lambda 或策略类,EBO 可以让 FuncWrapper
大小为 1 或 0 字节。
4 EBO 的限制
有虚函数或虚继承
struct Base {virtual void f() {}
};
- 虚表指针会阻止 EBO。
多个相同空基类
struct A {};
struct B1 : A {};
struct B2 : A {}; // 编译器不能合并两个 A 的地址struct C : B1, B2 {};
C++ 要保证每个 A
的子对象地址不同,因此不能优化掉两个 A
。
5 C++20 的 [[no_unique_address]]
为了手动控制 EBO,C++20 引入了 [[no_unique_address]]
属性:
template<typename T, typename Deleter>
struct SmartPtr {T* ptr;[[no_unique_address]] Deleter deleter; // 允许优化
};
- 即使
Deleter
是空类,编译器也不会强行分配空间; - 可应用于非基类成员(突破传统 EBO 只能作用于基类的限制);
- 可读性和语义性更好。
总结
项目 | 是否允许空对象优化 |
---|---|
空类作为成员 | ❌ 不允许,至少占 1 字节 |
空类作为非虚基类 | ✅ 可以优化掉空间 |
空类有虚函数/虚继承 | ❌ 无法优化(有 vptr) |
多继承多个相同空基类 | ❌ 需保留唯一地址,不能优化 |
C++20 [[no_unique_address]] | ✅ 可以显式允许成员优化 |
相关文章:
【C/C++】EBO空基类优化介绍
空对象优化(Empty Base Optimization,简称 EBO)是 C 编译器的一种 优化技术,用于消除空类作为基类时占用的内存空间,从而避免浪费空间、提升结构体或类的存储效率。 1 什么是“空对象”? 一个**空类&#…...

工作邮箱收到钓鱼邮件,点了链接进去无法访问,会有什么问题吗?
没事的,很可能是被安全网关拦截了。最近做勒索实验,有感而发,不要乱点击邮箱中的附件。 最初我们采用钓鱼邮件投递恶意载荷,发现邮件网关把我们的 exe/bat 程序直接拦截了,换成压缩包也一样拦截了,载荷始终…...

基于安卓的线上考试APP源码数据库文档
摘 要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐渐被人们所认识,科学化的管理,使信息存…...

【数据结构】顺序表和链表详解(下)
前言:上期我们从顺序表开始讲到了单链表的概念,分类,和实现,而这期我们来将相较于单链表没那么常用的双向链表。 文章目录 一、双向链表二,双向链表的实现一,增1,头插2,尾插3&#x…...

【系统架构设计师】绪论-系统架构概述
目录 绪论 系统架构概述 单选题 绪论 系统架构概述 单选题 1、软件方法学是以软件开发方法为研究对象的学科。其中,()是先对最高居次中的问题进行定义、设计、编程和测试,而将其中未解决的问题作为一个子任务放到下一层次中去…...

SQL-事务(2025.6.6-2025.6.7学习篇)
1、简介 事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。 默认MySQL的事务是自动提交的,也就是说࿰…...
OpenCV 图像通道的分离与合并
一、知识点 1、一张彩色图像可以由R、G、B三个通道的灰度图合并而成。 2、void split(InputArray m, OutputArrayOfArrays mv); (1)、将多通道阵列划分为几个单通道阵列。 (2)、参数说明: m: 要分离的多通道阵列。 mv: 输出的vector容器,每个元素都…...

Virtex II 系列FPGA的配置原理
对FPGA 芯片的配置,本质上是将根据设计生成的包含配置命令和配置数据的比特流文件写入到配置存储器中。 1 配置模式 Virtex II 系列FPGA 一共有五种配置模式,配置模式的选择是根据管脚M[2:0]来决定。 (1)串行配置模式 串行配置模…...

蓝桥杯 国赛2024python(b组)题目(1-3)
第一题 试卷答题页 - 蓝桥云课 问题描述 在今年蓝桥杯的决赛中,一共有 1010 道题目,每道题目的分数依次为 55 分,55 分,1010 分,1010 分,1515 分,1515 分,2020 分,2020 分…...
低代码平台前端页面表格字段绑定与后端数据传输交互主要有哪些方式?华为云Astro在这方面有哪些方式?
目录 🔧 一、低代码平台中常见的数据绑定与交互方式 1. 接口绑定(API 调用) 2. 数据源绑定(DataSource) 3. 变量中转(临时变量 / 页面状态) 4. 数据模型绑定(模型驱动) 🌐 二、华为云 Astro 轻应用的实现方式 ✅ 1. 数据源绑定(API服务+API网关) ✅ 2. 变…...
stm32——UART和USART
串口通信协议UART和USART 1. UART与USART协议详解 特性UART (Universal Asynchronous Receiver/Transmitter)USART (Universal Synchronous Asynchronous Receiver/Transmitter)全称通用异步收发器通用同步/异步收发器同步/异步异步:不共享时钟,数据通过…...

算法题(165):汉诺塔问题
审题: 本题需要我们找到最优的汉诺塔搬法然后将移动路径输出 思路: 方法一:递归 我们先分析题目 n为2的情况,我们先将第一个盘子移动到三号柱子上,然后再将二号盘子移动到二号柱子上 n为3的情况,我们先将前…...

玄机——某次行业攻防应急响应(带镜像)
今天给大家带来一次攻防实战演练复现的过程。 文章目录 简介靶机简介1.根据流量包分析首个进行扫描攻击的IP是2.根据流量包分析第二个扫描攻击的IP和漏扫工具,以flag{x.x.x.x&工具名}3.提交频繁爆破密钥的IP及爆破次数,以flag{ip&次数}提交4. 提…...

低代码逻辑引擎配置化实战:三步穿透审批记录查询
在堆积如山的报销单中埋头寻找某笔特殊费用的审批轨迹在跨部门协作时被追问"这个合同到底卡在哪个环节" 在快节奏的办公自动化场景中,这些场景是很常见的,传统OA系统中分散的审批记录查询方式往往太繁琐。 为破解这一痛点,在JVS低…...
深入理解React Hooks的原理与实践
深入理解React Hooks的原理与实践 引言 React Hooks 自 2018 年 React 16.8 发布以来,彻底改变了前端开发者的编码方式。它通过函数式组件提供了状态管理和生命周期等功能,取代了传统的类组件,使得代码更加简洁、复用性更强。然而ÿ…...
WEB3技术重要吗,还是可有可无?
我从几个角度给你一个全面、理性、技术导向的回答: ✅ 一、Web3 技术的重要性:“有意义,但不是万能” Web3 技术并不是可有可无的噱头,而是一种在特定场景下提供独特价值的技术体系。 它重要的原因包括: 1. 重构数字…...
Python 隐藏法宝:双下划线 _ _Dunder_ _
你可能不知道,Python里那些用双下划线包裹的"魔法方法"(Dunder方法),其实是提升代码质量的绝佳工具。但有趣的是,很多经验丰富的开发者对这些方法也只是一知半解。 先说句公道话: 这其实情有可原。因为在多数情况下&am…...
《视觉SLAM十四讲》自用笔记 第三讲:三维空间刚体运动
第三讲 三维空间刚体运动 3.0 目标 1.理解三维空间的刚体运动描述方式:旋转矩阵、变换矩阵、四元数和欧拉角。 2.掌握 Eigen 库的矩阵、几何模块使用方法。 3.1 旋转矩阵 3.1.1 点和向量,坐标系 三维空间中,刚体的运动可以用两个概念来…...

【Zephyr 系列 15】构建企业级 BLE 模块通用框架:驱动 + 事件 + 状态机 + 低功耗全栈设计
🧠关键词:Zephyr、BLE 模块、架构设计、驱动封装、事件机制、状态机、低功耗、可维护框架 📌面向读者:希望将 BLE 项目从“Demo 工程”升级为“企业可复用框架”的研发人员与技术负责人 📊预计字数:5500+ 字 🧭 前言:从 Demo 到产品化,架构该如何升级? 多数 BLE…...

Docker构建Vite项目内存溢出:从Heap Limit报错到完美解决的剖析
问题现象:诡异的"消失的index.html" 最近在CI/CD流水线中遇到诡异现象:使用Docker构建Vite项目时,dist目录中缺少关键的index.html文件,但本地构建完全正常。报错截图显示关键信息: FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out…...
Linux运维新人自用笔记(乌班图apt命令和dpkg命令、两系统指令区别,rpm解决路径依赖、免安装配置java环境)
内容全为个人理解和自查资料梳理,欢迎各位大神指点! 每天学习较为零散。 day17 一、Ubuntu apt命令和dpkg命令 二进制命令配置文件数据文件,打包好的单个文件 Windows :.exe macos:.dmg 后缀适用系统安装方式.d…...
vm+ubuntu24.04扩展磁盘
vmubuntu24.04扩展磁盘 $ lsblk $ sudo fdisk -l 1.修复 GPT 表警告 $ sudo parted /dev/sda print当询问是否修复时,输入 Fix2.扩展物理分区 /dev/sda3 $ sudo growpart /dev/sda 33.刷新物理卷 (PV) $ sudo pvresize /dev/sda3检查可用的扩展空间. $ sudo vgd…...
Python爬虫-爬取各省份各年份高考分数线数据,进行数据分析
前言 本文是该专栏的第60篇,后面会持续分享python爬虫干货知识,记得关注。 本文,笔者将基于Python爬虫,爬取各省份历年以来的“各年份高考分数线”进行数据分析。 废话不多说,具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。接下来,跟着笔者直接往下看…...

Android端口转发
如上图所示,有一个Android设备,Android设备里面有主板,主板上有网络接口和Wi-Fi,网络接口通过网线连接了一个网络摄像头,这就跟电脑一样,电脑即可以通过网线接入一个网络,也可以同时用Wi-Fi接入…...
C语言 | C代码编写中的易错点总结
C语言易错点 **1. 指针与内存管理****2. 数组与字符串****3. 未初始化变量****4. 类型转换与溢出****5. 运算符优先级****6. 函数与参数传递****7. 宏定义陷阱****8. 结构体与内存对齐****9. 输入/输出函数****10. 其他常见问题****最佳实践**在C语言编程中,由于其底层特性和灵…...

PHP环境极速搭建
一、为什么选择phpStudy VS Code? 作为一名初次接触PHP的开发者,我深知环境配置往往是学习路上的第一道门槛。传统PHP环境搭建需要手动配置Apache/Nginx、PHP解释器、MySQL等多重组件,光是处理版本兼容性和依赖问题就可能耗费半天时间——这…...

建造者模式深度解析与实战应用
作者简介 我是摘星,一名全栈开发者,专注 Java后端开发、AI工程化 与 云计算架构 领域,擅长Python技术栈。热衷于探索前沿技术,包括大模型应用、云原生解决方案及自动化工具开发。日常深耕技术实践,乐于分享实战经验与…...

代码中文抽取工具并替换工具(以ts为例)
文章目录 基本思路目录结构配置文件AST解析替换代码中文生成Excel启动脚本 基本思路 通过对应语言的AST解析出中文相关信息(文件、所在行列等)存到临时文件通过相关信息,逐个文件位置替换掉中文基于临时文件,通过py脚本生成Excel…...

pgsql batch insert optimization (reWriteBatchedInserts )
reWriteBatchedInserts 是 PostgreSQL JDBC 驱动 提供的一个优化选项,它可以 重写批量插入语句,从而提高插入性能。 作用 当 reWriteBatchedInsertstrue 时,PostgreSQL JDBC 驱动会将 多个单独的 INSERT 语句 转换为 一个多行 INSERT 语句&a…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(上)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...