小编典典

PIMPL 成语真的在实践中使用吗?

all

我正在阅读 Herb Sutter 的 “Exceptional C++” 一书,在那本书中我了解了 PIMPL 习语。基本上,这个想法是为 a
private对象创建一个结构class并动态分配它们以 减少编译时间 (并以更好的方式隐藏私有实现)。

例如:

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

可以改为:

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

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

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

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

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


阅读 184

收藏
2022-08-17

共1个答案

小编典典

所以,我想知道这种技术是否真的在实践中使用?我应该在任何地方使用它,还是谨慎使用?

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


使用 PIMPL 成语的原因:

二进制兼容性

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

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

数据隐藏

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

编译时间

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

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

更重要的是,即使在添加和更改XClient1.cpp私有方法时,也需要重新编译标准头/实现分离,即使出于封装原因不可能调用此方法!像上面一样,它是纯粹的开销,并且与现实生活中的
C++ 构建系统的工作方式有关。X::foo()``X``X.h``XClient1.cpp

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


是否建议将此技术用于嵌入式系统(性能非常重要)?

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

2022-08-17