【问题标题】:pimpl-idiom in template; which smart pointer?模板中的 pimpl-idiom;哪个智能指针?
【发布时间】:2012-01-13 06:18:32
【问题描述】:

我通常对 pimpl 使用 boost::scoped_ptr(原因之一是如果我忘记处理复制构造函数,我不会感到惊讶)

但是,对于模板,我不能将析构函数放在完全定义了 impl 的 cpp 文件中,以满足 scoped_ptr 析构函数的要求。无论如何它确实有效,但我不确定它是保证有效还是偶然。是否有一些“最佳实践”或标准? scoped_ptr 是不可复制类中 pimpls 的最佳智能指针吗?

template <class T> class C {
public:
    C(){}
    ~C(){}
private:
    boost::scoped_ptr<T> pimpl_;
};

【问题讨论】:

  • 这种 PIMPL 实现没有任何意义,因为要实例化 C 模板,您必须了解类型 T。另一方面,PIMPL 对用户完全隐藏了 T 的等价物.
  • @VladLazarenko 嗯,我认为 boost::scoped_ptr 在预先声明的类上也能正常工作。在这种情况下,它取决于 T 是定义的还是预先声明的。这个 scoped_ptr 的实例化将隐藏在实现中 (pimpl_(new T())。
  • @DavidFeurle:不是真的,为了让这个模板工作,T 的大小,以及它的接口,必须暴露,因为“客户”需要实例化模板。例如,您在哪里拨打new T()?您不能将其隐藏在“cpp”文件中,因为它必须在模板中。所以它不是 PIMPL。
  • @Vlad Lazarenko 好点。我知道我在哪里犯了错误以及它为什么会起作用
  • 所以看起来在这种情况下,因为无论如何我都必须定义 T,所以我只能将其设为私有成员以节省成本。

标签: c++ templates boost pimpl-idiom scoped-ptr


【解决方案1】:

恰好 Herb Sutter 时隔很久又开始写他的 GotWs。第一个新的与“编译防火墙”有关。

你可能想看看:

GotW #100: Compilation Firewalls (Difficulty: 6/10)

GotW #101: Compilation Firewalls, Part 2 (Difficulty: 8/10)

【讨论】:

  • 酷我喜欢他的书。他似乎已经回答了我关于使用 unique_ptr 使用什么指针类型的问题。
  • 看起来 Herb 接受了越复杂越好的理念。他所有基于标准的解决方案都引入了额外的复杂性,却没有真正的收益。
【解决方案2】:

两年后,为了保持堆栈溢出答案的相关性和最新性,我对这种情况有了更好的了解,这就是我今天将如何回答这个问题。

我最初问题的前提有些缺陷。使用 pimpl-idiom 的原因是对编译器隐藏实现细节。这是通过通过不透明指针(指向已声明但未定义的数据类型的指针)存储实现来完成的。这可以大大减少与类交互的其他编译单元所需的头文件数量,从而加快编译时间。在我的问题中的模板的情况下,需要在实例化点完全知道类型 T,这实际上需要在使用 C&lt;ImplType&gt; 的任何地方完全定义 impl 的类型,这显然不是 pimpl 的示例- 经典意义上的成语。

通过私有指针保存类数据还有其他原因,例如,它允许轻松实现无抛出移动和交换,并且如果您的类需要满足强大的异常保证(请参阅复制和交换成语What is the copy-and-swap idiom?)。另一方面,它在每次访问 impl 时添加了一层间接层(通常导致缓存未命中),并在创建和销毁 impl 时添加堆分配/释放。这些可能是严重的性能损失,因此不应将此解决方案视为灵丹妙药。

如果您可以使用 C++11,则应使用 std::unique_ptr 而不是 boost::scoped_ptr。

【讨论】:

    【解决方案3】:

    boost::shared_ptr 不需要完整的定义,除了 at 实例化点——在构造函数中,在 粉刺。 boost::shared_ptr 适合 pimpl 成语, 然而,因为它给出了非常意想不到的语义(参考语义 转让或复制);如果你真的想要增加复杂性 智能指针,boost::scoped_ptr 会更合适(但它 确实需要一个完整的定义,它的析构函数是 实例化)。

    关于模板,使用 pimpl 成语是没有意义的 标题中的实现细节。在export不在的情况下, 必须包含类模板的所有实现细节 到处使用模板,所以 pimpl 背后的动机 成语不复存在了。

    【讨论】:

      猜你喜欢
      • 2012-10-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多