模板中的粉刺习语;哪个智能指针



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

然而,对于模板,我不能仅仅将析构函数放在完全定义了impl的cpp文件中,以满足scoped_ptr的析构函数的要求。它确实有效,但我不确定它是否保证有效或只是偶然。是否存在一些"最佳实践"或标准?scoped_ptr是不可复制类中粉刺的最佳智能指针吗?
template <class T> class C {
public:
    C(){}
    ~C(){}
private:
    boost::scoped_ptr<T> pimpl_;
};

正好Herb Sutter在很长一段时间后又开始写他的GotWs。第一个新特性与"编译防火墙"有关。

你可能想看一下:

GotW #100:编译防火墙(难度:6/10)

GotW #101:编译防火墙,第2部分(难度:8/10)

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

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

通过私有指针保存类数据还有其他原因,例如,它允许轻松实现无抛出移动和交换,并且如果您的类需要实现强异常保证(参见复制和交换习惯用法什么是复制和交换习惯用法?)另一方面,它在每次访问impl时都增加了一个间接层(通常导致缓存丢失),并在创建和销毁impl时进行堆分配/回收。这些可能会造成很大的性能损失,因此不应将此解决方案视为灵丹妙药。

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

boost::shared_ptr不需要除at之外的完整定义构造函数中的实例化点,在a的情况下pimpl。boost::shared_ptr 适合痘痘习语,然而,由于它提供了非常意想不到的语义(引用语义)转让或复印);如果你真的想增加a的复杂度智能指针,boost::scoped_ptr将更合适(但它是否在析构函数所在的位置需要一个完整的定义实例化)。

对于模板来说,使用pimpl习惯用法是没有意义的头文件中的实现细节。在没有export的情况下,必须包含类模板的所有实现细节到处都是模板,所以痘痘背后的动机成语不再存在

最新更新