5

所以我一直在考虑 PIMPL 和堆栈分配。我一直在编写一个库,并决定使用 PIMPL 来隐藏该类的私有成员。这意味着我会有一个像这样声明的类

class Foo {
private:
    class Handle;
    std::tr1::shared_ptr<Handle> handle;
public:
    Foo();
};

这很简单。但是然后在构造函数中你这样做

Foo::Foo() : handle(new Handle()) {}

因此,当有人使用我的库在堆栈上创建 Foo 时,他们本质上是在进行堆分配。这是您在使用 PIMPL 时必须接受的权衡吗?我想在构造函数旁边发布带有警告的文档:“警告:这会导致堆分配”或类似的东西。

我的另一个想法是让所有暴露给实现的类作为纯虚拟接口和一大堆返回智能指针的静态工厂方法。这也意味着堆分配,但没有任何技巧。

有什么想法或建议吗?我是否过分考虑使用我的库的程序员?

4

2 回答 2

4

这是您在使用 PIMPL 时必须接受的权衡吗?

实际上,是的,尽管有一些技术,例如 Herb Sutter 在“The Fast Pimpl Idiom”中讨论的那些技术,可以用来消除或加速堆分配,但代价是更大的复杂性。

我想在构造函数旁边发布带有警告的文档:“警告:这会导致堆分配”或类似的东西。

仅当有必要这样做时(即,仅当您的用户会对您的类执行堆分配这一事实感到惊讶时)。许多类执行堆分配,包括 C++ 标准库中的许多类(例如所有容器)。

我是否过分考虑使用我的库的程序员?

可能:-)。除非你对你的类有很高的性能要求,或者你期望你的类的实例被非常频繁地创建和销毁,否则我不会太担心它。当然,如果您确实有很大的性能要求,那么 pimpl 可能不是一个好的选择。

于 2010-07-11T02:37:47.343 回答
4

因此,当有人使用我的库在堆栈上创建 Foo 时,他们本质上是在进行堆分配。这是您在使用 PIMPL 时必须接受的权衡吗?

是的。

我想在构造函数旁边发布带有警告的文档:“警告:这会导致堆分配”或类似的东西。

我会考虑过度激进的评论:) 如果您的课程对性能至关重要,也许您应该避免使用 PIMPL 成语。如果您代表一个数字,这可能是令人担忧且值得注意的。如果您要隐藏数据库连接的实现,则不值得评论:)

我的另一个想法是让所有暴露给实现的类作为纯虚拟接口和一大堆返回智能指针的静态工厂方法。这也意味着堆分配,但没有任何技巧。

是的,这对用户来说更明显一些,但同样可能不值得担心自己。

有什么想法或建议吗?我是否过分考虑使用我的库的程序员?

有一个权衡,但如果你的类足够复杂,可以真正从 pimpl 习语中获益,你可能可以假设堆分配是可以的。如果我使用你的图书馆,它可能不会关心我。

于 2010-07-11T02:42:44.970 回答