PIMPL и распределение стека

Так что я думал о PIMPL и распределении стека. Я писал библиотеку и решил использовать PIMPL, чтобы скрыть приватного члена класса. Это означает, что я бы объявил класс, как это

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

Это довольно просто. Но тогда в конструкторе вы делаете это

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

Поэтому, когда кто-то, использующий мою библиотеку, создает Foo в стеке, он, по сути, все равно выполняет выделение кучи. Это компромисс, с которым вам придется жить при использовании PIMPL? Я думал о выпуске документации с предупреждением рядом с конструкторами: "ПРЕДУПРЕЖДЕНИЕ: это приводит к выделению кучи" или что-то подобное.

Моя другая мысль состояла в том, чтобы все классы были представлены в виде чистых виртуальных интерфейсов, а целая куча статических фабричных методов возвращала умные указатели. Это также означает распределение кучи, но в этом нет никакой хитрости.

Есть мысли или предложения? Я слишком внимателен к программистам, использующим мою библиотеку?

2 ответа

Решение

Это компромисс, с которым вам придется жить при использовании PIMPL?

По сути, да, хотя существуют методы, подобные тем, которые обсуждались Хербом Саттером в "Быстрой фразеологии Pimpl", которые можно использовать для устранения или ускорения выделения кучи за счет большей сложности.

Я думал о выпуске документации с предупреждением рядом с конструкторами: "ПРЕДУПРЕЖДЕНИЕ: это приводит к выделению кучи" или что-то подобное.

Только если это необходимо (т. Е. Только если ваши пользователи будут удивлены тем, что ваш класс выполнил распределение кучи). Многие классы выполняют выделение кучи, в том числе многие из них в стандартной библиотеке C++ (например, во всех контейнерах).

Я слишком внимателен к программистам, использующим мою библиотеку?

Возможно:-). Если вы не предъявляете высокие требования к производительности для своего класса или не ожидаете, что экземпляры вашего класса будут создаваться и уничтожаться слишком часто, я бы не стал сильно беспокоиться об этом. Конечно, если у вас есть значительные требования к производительности, pimpl может быть не лучшим выбором.

Поэтому, когда кто-то, использующий мою библиотеку, создает Foo в стеке, он, по сути, все равно выполняет выделение кучи. Это компромисс, с которым вам придется жить при использовании PIMPL?

Ага.

Я думал о выпуске документации с предупреждением рядом с конструкторами: "ПРЕДУПРЕЖДЕНИЕ: это приводит к выделению кучи" или что-то подобное.

Я бы посчитал это чрезмерным комментированием:) Если ваш класс настолько критичен по производительности, возможно, вам следует избегать идиомы PIMPL. Если вы представляете число, это может быть важно и стоит отметить. Если вы скрываете реализацию подключения к базе данных, не стоит комментировать:)

Моя другая мысль состояла в том, чтобы все классы были представлены в виде чистых виртуальных интерфейсов, а целая куча статических фабричных методов возвращала умные указатели. Это также означает распределение кучи, но в этом нет никакой хитрости.

Да, это немного более очевидно для пользователя, но опять же, вероятно, не стоит беспокоиться о себе.

Есть мысли или предложения? Я слишком внимателен к программистам, использующим мою библиотеку?

Есть компромисс, но если ваш класс достаточно сложен, чтобы действительно извлечь выгоду из идиомы pimpl, вы, вероятно, можете считать, что распределение кучи в порядке. Если бы я использовал вашу библиотеку, это, вероятно, не касалось бы меня.

Другие вопросы по тегам