PIMPL 习惯用法真的在实践中使用吗?

2024-01-10

我正在看书“卓越的 C++”Herb Sutter 所著,在那本书中我了解了 PIMPL 习惯用法。基本上,这个想法是创建一个结构private的对象class并将它们动态分配给减少编译时间(并且还以更好的方式隐藏私有实现)。

例如:

class X
{
private:
  C c;
  D d;
} ;

可以改为:

class X
{
private:
  struct XImpl;
  XImpl* pImpl;
};

并且,在 .cpp 文件中定义:

struct X::XImpl
{
  C c;
  D d;
};

这看起来相当有趣,但我以前从未见过这种做法,无论是在我工作过的公司中,还是在我见过源代码的开源项目中。所以,我想知道这种技术是否真的用于实践。

我应该在任何地方使用它还是谨慎使用?这种技术是否建议用于嵌入式系统(其中性能非常重要)?


那么,我想知道这种技术真的在实践中得到应用吗?我应该在任何地方使用它还是谨慎使用?

当然是用的。我在我的项目中,几乎在每堂课上都使用它。


使用 PIMPL 习惯用法的原因:

二进制兼容性

当您开发库时,您可以添加/修改字段XImpl不会破坏与客户端的二进制兼容性(这意味着崩溃!)。由于二进制布局X当您添加新字段时,类不会改变Ximpl类,在次要版本更新中向库添加新功能是安全的。

当然,你也可以添加新的公共/私有非虚拟方法X/XImpl不会破坏二进制兼容性,但这与标准标头/实现技术相当。

数据隐藏

如果您正在开发一个库,尤其是一个专有库,那么最好不要透露使用了哪些其他库/实现技术来实现您的库的公共接口。要么是因为知识产权问题,要么是因为您认为用户可能会对实现做出危险的假设,或者只是通过使用可怕的转换技巧来破坏封装。 PIMPL 解决/缓解了这个问题。

编译时间

编译时间减少,因为只有源(实现)文件X当您添加/删除字段和/或方法时需要重建XImpl类(映射到在标准技术中添加私有字段/方法)。实际上,这是一个常见的操作。

使用标准标头/实现技术(无 PIMPL),当您向X,每个分配过的客户X(无论是在堆栈上,还是在堆上)需要重新编译,因为它必须调整分配的大小。好吧,每个不分配 X 的客户端also需要重新编译,但这只是开销(客户端的结果代码将是相同的)。

更重要的是,通过标准头文件/实现分离XClient1.cpp即使是私有方法也需要重新编译X::foo()被添加到X and X.h改变了,尽管XClient1.cpp由于封装原因不可能调用此方法!如上所述,它是纯粹的开销,并且与现实生活中的 C++ 构建系统的工作方式有关。

当然,当您只修改方法的实现时,不需要重新编译(因为您没有触及标头),但这与标准标头/实现技术相同。


是否建议在嵌入式系统(性能非常重要)中使用该技术?

这取决于你的目标有多强大。然而,这个问题的唯一答案是:衡量和评估你的所得和失去。另外,请考虑到,如果您不发布供客户在嵌入式系统中使用的库,则只有编译时间优势适用!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

PIMPL 习惯用法真的在实践中使用吗? 的相关文章

  • 为什么使用abs()或fabs()而不是条件否定?

    在 C C 中 为什么要使用abs or fabs 不使用以下代码即可查找变量的绝对值 int absoluteValue value lt 0 value value 这与较低级别的指令较少有关吗 您提出的 有条件的abs 并不等于std
  • GCC C++ (ARM) 和指向结构体字段的 const 指针

    假设有一个简单的测试代码 typedef struct int first int second int third type t define ADDRESS 0x12345678 define REGISTER type t ADDRE
  • Tensorflow 中的自定义资源

    由于某些原因 我需要为 Tensorflow 实现自定义资源 我试图从查找表实现中获得灵感 如果我理解得好的话 我需要实现3个TF操作 创建我的资源 资源的初始化 例如 在查找表的情况下填充哈希表 执行查找 查找 查询步骤 为了促进实施 我
  • Mono 无法保存用户设置

    我在 Mono Ubuntu 上保存用户设置时遇到问题 这是代码示例 private void Form1 Load object sender EventArgs e string savedText Properties Setting
  • Qt - 无法让 lambda 工作[重复]

    这个问题在这里已经有答案了 我有以下功能 我想在其中修剪我的std set
  • 在 OpenCL 中将函数作为参数传递

    是否可以在 OpenCL 1 2 中将函数指针传递给内核 我知道可以用C实现 但不知道如何在OpenCL的C中实现 编辑 我想做这篇文章中描述的同样的事情 在 C 中如何将函数作为参数传递 https stackoverflow com q
  • 捕获 foreach 条件中抛出的异常

    我有一个foreach在 foreach 本身的条件下循环期间中断的循环 有没有办法try catch抛出异常然后继续循环的项 这将运行几次 直到异常发生然后结束 try foreach b in bees exception is in
  • 通信对象 System.ServiceModel.Channels.ServiceChannel 不能用于通信

    通信对象System ServiceModel Channels ServiceChannel 无法用于通信 因为它处于故障状态 这个错误到底是什么意思 我该如何解决它 您收到此错误是因为您让服务器端发生 NET 异常 并且您没有捕获并处理
  • Linux TUN/TAP:无法从 TAP 设备读回数据

    问题是关于如何正确配置想要使用 Tun Tap 模块的 Linux 主机 My Goal 利用现有的路由软件 以下为APP1和APP2 但拦截并修改其发送和接收的所有消息 由Mediator完成 我的场景 Ubuntu 10 04 Mach
  • TextBox 焦点的 WinForms 事件?

    我想添加一个偶数TextBox当它有焦点时 我知道我可以用一个简单的方法来做到这一点textbox1 Focus并检查布尔值 但我不想那样做 我想这样做 this tGID Focus new System EventHandler thi
  • 为什么密码错误会导致“填充无效且无法删除”?

    我需要一些简单的字符串加密 所以我编写了以下代码 有很多 灵感 来自here http www codeproject com KB security DotNetCrypto aspx create and initialize a cr
  • 范围和临时初始化列表

    我试图将我认为是纯右值的内容传递到范围适配器闭包对象中 除非我将名称绑定到初始值设定项列表并使其成为左值 否则它不会编译 这里发生了什么 include
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • 过期时自动重新填充缓存

    我当前缓存方法调用的结果 缓存代码遵循标准模式 如果存在 则使用缓存中的项目 否则计算结果 在返回之前将其缓存以供将来调用 我想保护客户端代码免受缓存未命中的影响 例如 当项目过期时 我正在考虑生成一个线程来等待缓存对象的生命周期 然后运行
  • gdb查找行号的内存地址

    假设我已将 gdb 附加到一个进程 并且在其内存布局中有一个文件和行号 我想要其内存地址 如何获取文件x中第n行的内存地址 这是在 Linux x86 上 gdb info line test c 56 Line 56 of test c
  • 为什么 Ajax.BeginForm 在 Chrome 中不起作用?

    我正在使用 c NET MVC2 并尝试创建一个 ajax 表单来调用删除数据库记录 RemoveRelation 的方法 删除记录的过程正在按预期进行 删除记录后 表单应调用一个 JavaScript 函数 从视觉效果中删除该记录 Rem
  • 在基类集合上调用派生方法

    我有一个名为 A 的抽象类 以及实现 A 的其他类 B C D E 我的派生类持有不同类型的值 我还有一个 A 对象的列表 abstract class A class B class A public int val get privat
  • Swagger 为 ASP.CORE 3 中的字典生成错误的 URL

    当从查询字符串中提取的模型将字典作为其属性之一时 Swagger 会生成不正确的 URL 如何告诉 Swagger 更改 URL 中字典的格式或手动定义输入参数模式而不自动生成 尝试使用 Swashbuckle 和 NSwag 控制器 pu
  • Azure函数版本2.0-应用程序blobTrigger不工作

    我有一个工作功能应用程序 它有一个 blob 输入和一个事件中心输出 在测试版中工作 随着最新的更改 我的功能不再起作用 我尝试根据发行说明更新 host json 文件 但它没有引用 blob 触发器 version 2 0 extens
  • 从类模板参数为 asm 生成唯一的字符串文字

    我有一个非常特殊的情况 我需要为类模板中声明的变量生成唯一的汇编程序名称 我需要该名称对于类模板的每个实例都是唯一的 并且我需要将其传递给asm关键字 see here https gcc gnu org onlinedocs gcc 12

随机推荐

  • PHP 数组...空括号的含义是什么?

    我遇到了一些示例代码 如下所示 form submit annotate admin settings submit 为什么 submit 后面有一个空的括号 里面什么都没有 这意味着什么 谁能给我举个例子吗 通常 根据我的理解 这可能是错
  • 双递归定义列表的双无限列表

    Context 我问的是修补递归定义的列表 https stackoverflow com q 53988970 12274另一天 我现在尝试通过在 2D 列表 列表的列表 上操作来将其提升一个级别 我将使用帕斯卡三角形作为示例 例如这个美
  • 如何在字符串中找到匹配的大括号对?

    假设我有一个字符串 付费 8个工作时间 公司规则 现在我想检查这个完整的字符串是否用括号括起来 基本上我想检查字符串是否是这样的 付费 8个工作时间 公司规则 如果它已经用括号括起来 那么我将保留它原样 否则我会将括号应用于完整的字符串 以
  • 如何从多行文本框中获取换行?

    在我的 windows forms C 应用程序中 我有一个 WordWrap true 的多行文本框 将 Text 属性设置为长字符串后 我需要获取通过换行生成的所有行 它与 Lines 属性不同 因为我的文本不包含换行符 我已经找到了使
  • 在启用自动筛选器且数据位于“要复制的行”的情况下,将一行复制并添加到工作表的末尾

    更新 替代解决方案不幸的是 我的问题没有答案 我需要继续该项目 我查看了之前编写的一些代码并决定使用它 我发现的解决方案不如用户 djbrett 建议的解决方案优雅 但它有效 我添加了一行额外的行 宏可以从中继续计数 有兴趣的可以看下面的代
  • 如何记录基于函数的视图参数?

    我正在使用 Django 1 11 和 Django REST Framework 3 7 开发 REST API 我安装了Django REST 招摇 https github com marcgibbons django rest sw
  • Clojure 实现可以快速启动吗?

    time java jar clojure 1 4 0 jar e println Hello world Hello world real 0m4 586s time python clojure py c py print Hello
  • 错误:tensorboard 2.0.2 要求 setuptools>=41.0.0,但您将拥有不兼容的 setuptools 40.6.2

    安装的时候出现这个错误 这会引起问题吗 错误 tensorboard 2 0 2 要求 setuptools gt 41 0 0 但您将拥有不兼容的 setuptools 40 6 2 我刚刚做了一个pip install setuptoo
  • 持久图形 WinForms

    我有一个 WinForms 应用程序 我必须在控件之间画一些线 这些行需要持久存在 所以我覆盖了表单OnPaint event 问题是 重新绘制的线条不是很平滑 我正在创建图形如下 Graphics g g this CreateGraph
  • 警告来源未知:“找不到虚拟表的链接器符号...”

    几天以来 我在调试时收到一条警告消息 我找不到它来自哪里 我已经在谷歌搜索并发现类似的东西 因为我有一个静态变量 但取出来并不能改变什么 这是main method int main int argc char argv if argc 2
  • 如何列出连接字符串列表的所有可能方法

    我想列出连接字符串列表的所有可能方法 例如 Input strings hat bag cab Output concatenated hatbag hatcab hatbagcab hatcabbag baghat bagcab bagh
  • 使用 JS 切换/显示一个定义的 DIV

    我有一把小提琴给你 http jsfiddle net vSs4f http jsfiddle net vSs4f 我想展示div sub menu只需点击一下a haschildren 如果身体加载div sub menu应该关闭 如果我
  • 将 VS2010 类图导出到 Visio

    我正在使用 VS2010 创建类图 有什么方法可以导入 VS2010 生成的类图以导入到 MS Visio 中吗 右键单击 Visual Studio 中的类图 然后选择 将图导出为图像 Choose 增强型图元文件格式 emf Visio
  • Spring Integration 中的 REST 端点使消息通道成为多线程

    我有一个非常简单的 Spring Boot 应用程序 它提供了几个静态端点 这应该驱动将 sftp 文件上传到 sftp 服务器 我的要求是 如果有多个文件 则文件应该排队 我希望通过 sftp spring 集成工作流程的默认行为来实现这
  • 使用 DOMXPath 保留

    标签内的换行符?

    我目前正在使用 PHP 和DOMXPath获取所有的内容 p 网页的元素 p
  • 如何过滤 SCons Glob 结果?

    我有时想从 SCons 的 Glob 结果中排除某些源文件 通常是因为我想用不同的选项编译该源文件 像这样的事情 objs env Object Glob cc objs env Object SpeciallyTreatedFile cc
  • 如何在不更改图像的情况下更新ALAsset的exif?

    I use setImageData metadata completionBlock of ALAsset更新资产的 exif 元数据 我只想更新元数据 但此方法需要imageData作为第一个参数 我使用下面的代码来生成imageDat
  • jQuery.event.props 未定义

    我在用着jquery event move https github com stephband jquery event move在触摸设备上创建移动事件 该脚本在第 580 行抛出错误 570 Make jQuery copy touc
  • 地理定位在设备 ionic3 中不起作用

    我正在从事 ionic 3 基于位置的工作 我无法在这里获取当前位置的纬度和经度 我提到了我的可用代码 它在浏览器级别工作正常 但在移动设备中无法工作 code ionic cordova plugin add cordova plugin
  • PIMPL 习惯用法真的在实践中使用吗?

    我正在看书 卓越的 C Herb Sutter 所著 在那本书中我了解了 PIMPL 习惯用法 基本上 这个想法是创建一个结构private的对象class并将它们动态分配给减少编译时间 并且还以更好的方式隐藏私有实现 例如 class X