所以我一直在考虑PIMPL和堆栈分配。我一直在写一个库,并决定使用PIMPL隐藏该类的私有成员。这意味着我会有一个像这样宣布的类
class Foo {
private:
class Handle;
std::tr1::shared_ptr<Handle> handle;
public:
Foo();
};
这很直截了当。但是然后在构造函数中执行此操作
Foo::Foo() : handle(new Handle()) {}
因此,当使用我的库的人在堆栈上创建Foo时,他们实际上是在进行堆分配。这是使用PIMPL时必须要考虑的权衡吗?我想在构造函数旁边发出警告释放文档:“警告:这会导致堆分配”或者其他一些问题。
我的另一个想法是将所有暴露给实现的类作为纯虚拟接口和一大堆静态工厂方法返回智能指针。这也意味着堆分配,但没有技巧。
有什么想法或建议吗?我是否过度考虑使用我的库的程序员?
答案 0 :(得分:4)
使用PIMPL时,这是否需要权衡利弊?
实际上,是的,虽然有一些技术,例如Herb Sutter在"The Fast Pimpl Idiom,"中讨论过的技术,可以用来消除或加快堆分配,但代价是更复杂。
我想在构造函数旁边发出警告释放文档:“警告:这会导致堆分配”或者其他一些。
只有在必要时才这样做(即,只有当您的用户对您的类执行堆分配这一事实感到惊讶时)。许多类执行堆分配,包括C ++标准库中的许多(例如,所有容器)。
我是否过度考虑使用我的库的程序员?
可能:-)。除非你对你的课程有很高的性能要求,或者你希望你的课程实例经常被创造和销毁,我不会过分担心它。当然,如果你确实有很高的性能要求,那么pimpl可能不是一个好的选择。
答案 1 :(得分:4)
因此,当使用我的库的人在堆栈上创建Foo时,他们实际上是在进行堆分配。这是使用PIMPL时必须要考虑的权衡吗?
是的。
我想在构造函数旁边发出警告释放文档:“警告:这会导致堆分配”或者其他一些。
我认为过于激进的评论:)如果你的课程性能如此重要,也许你应该避免使用PIMPL习语。如果你代表一个数字,这可能是令人担忧的,值得注意。如果您正在隐藏数据库连接的实现,则不值得评论:)
我的另一个想法是将所有暴露给实现的类作为纯虚拟接口和一大堆静态工厂方法返回智能指针。这也意味着堆分配,但没有技巧。
是的,这对用户来说更明显一些,但可能不值得关注自己。
有什么想法或建议吗?我是否过度考虑使用我的库的程序员?
有一个权衡,但是如果你的类很复杂到可以从pimpl习语中获得真正的好处,你可能会认为堆分配是可以的。如果我使用你的图书馆,可能不会让我感到担心。