【C/C++】EBO空基类优化介绍

news2025/6/9 9:55:35

空对象优化(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 成员,因此占用额外空间;
  • OptimizedEmpty 作为基类,如果没有虚函数/虚继承,编译器可以完全消除其空间。

3 EBO 的典型应用场景

标准库容器优化

STL 中 std::functionstd::tuplestd::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]]✅ 可以显式允许成员优化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2405211.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

工作邮箱收到钓鱼邮件,点了链接进去无法访问,会有什么问题吗?

没事的&#xff0c;很可能是被安全网关拦截了。最近做勒索实验&#xff0c;有感而发&#xff0c;不要乱点击邮箱中的附件。 最初我们采用钓鱼邮件投递恶意载荷&#xff0c;发现邮件网关把我们的 exe/bat 程序直接拦截了&#xff0c;换成压缩包也一样拦截了&#xff0c;载荷始终…

基于安卓的线上考试APP源码数据库文档

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

【数据结构】顺序表和链表详解(下)

前言&#xff1a;上期我们从顺序表开始讲到了单链表的概念&#xff0c;分类&#xff0c;和实现&#xff0c;而这期我们来将相较于单链表没那么常用的双向链表。 文章目录 一、双向链表二&#xff0c;双向链表的实现一&#xff0c;增1&#xff0c;头插2&#xff0c;尾插3&#x…

【系统架构设计师】绪论-系统架构概述

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

SQL-事务(2025.6.6-2025.6.7学习篇)

1、简介 事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0c;要么同时失败。 默认MySQL的事务是自动提交的&#xff0c;也就是说&#xff0…

Virtex II 系列FPGA的配置原理

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

蓝桥杯 国赛2024python(b组)题目(1-3)

第一题 试卷答题页 - 蓝桥云课 问题描述 在今年蓝桥杯的决赛中&#xff0c;一共有 1010 道题目&#xff0c;每道题目的分数依次为 55 分&#xff0c;55 分&#xff0c;1010 分&#xff0c;1010 分&#xff0c;1515 分&#xff0c;1515 分&#xff0c;2020 分&#xff0c;2020 分…

算法题(165):汉诺塔问题

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

玄机——某次行业攻防应急响应(带镜像)

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

低代码逻辑引擎配置化实战:三步穿透审批记录查询

在堆积如山的报销单中埋头寻找某笔特殊费用的审批轨迹在跨部门协作时被追问"这个合同到底卡在哪个环节" 在快节奏的办公自动化场景中&#xff0c;这些场景是很常见的&#xff0c;传统OA系统中分散的审批记录查询方式往往太繁琐。 为破解这一痛点&#xff0c;在JVS低…

【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…

Android端口转发

如上图所示&#xff0c;有一个Android设备&#xff0c;Android设备里面有主板&#xff0c;主板上有网络接口和Wi-Fi&#xff0c;网络接口通过网线连接了一个网络摄像头&#xff0c;这就跟电脑一样&#xff0c;电脑即可以通过网线接入一个网络&#xff0c;也可以同时用Wi-Fi接入…

PHP环境极速搭建

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

建造者模式深度解析与实战应用

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

代码中文抽取工具并替换工具(以ts为例)

文章目录 基本思路目录结构配置文件AST解析替换代码中文生成Excel启动脚本 基本思路 通过对应语言的AST解析出中文相关信息&#xff08;文件、所在行列等&#xff09;存到临时文件通过相关信息&#xff0c;逐个文件位置替换掉中文基于临时文件&#xff0c;通过py脚本生成Excel…

pgsql batch insert optimization (reWriteBatchedInserts )

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

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(上)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…

华为云Flexus+DeepSeek征文 | 基于DeepSeek-V3构建企业知识库问答机器人实战

作者简介 我是摘星&#xff0c;一名专注于云计算和AI技术的开发者。本次通过华为云MaaS平台体验DeepSeek系列模型&#xff0c;将实际使用经验分享给大家&#xff0c;希望能帮助开发者快速掌握华为云AI服务的核心能力。 目录 作者简介 1. 引言 2. 技术选型与架构设计 2.1 技…

【Docker 01】Docker 简介

&#x1f308; 一、虚拟化、容器化 ⭐ 1. 什么是虚拟化、容器化 物理机&#xff1a;真实存在的服务器 / 计算机&#xff0c;对于虚拟机来说&#xff0c;物理机为虚拟机提供了硬件环境。虚拟化&#xff1a;通过虚拟化技术将一台计算机虚拟为 1 ~ n 台逻辑计算机。在一台计算机…