pimpl-идиома в шаблоне;какой умный указатель? - PullRequest
6 голосов
/ 05 декабря 2011

Я обычно использую boost :: scoped_ptr для pimpl (по одной причине, потому что тогда я не получу сюрпризов, если забуду разобраться с конструктором копирования)

Однако с помощью шаблонов я не могу просто поместить деструктор в файл cpp, где impl полностью определен, чтобы выполнить требования деструктора scoped_ptr. Это все равно работает, но я не уверен, гарантировано ли это работает или просто случайно. Есть ли «лучшая практика» или стандарт? Является ли scoped_ptr лучшим интеллектуальным указателем для прыщей в не копируемых классах?

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

Ответы [ 3 ]

13 голосов
/ 05 декабря 2011

Просто так случилось, что Херб Саттер снова начал писать свои GotWs после долгого времени. Один из первых новых связан с «Брандмауэрами компиляции».

Возможно, вы захотите взглянуть на:

ПОЛУЧИЛО # 100: Компиляционные брандмауэры (Сложность: 6/10)

и

ПОЛУЧИЛСЯ # 101: Компиляционные брандмауэры, часть 2 (сложность: 8/10)

2 голосов
/ 11 июня 2014

Два года спустя я гораздо лучше понимаю ситуацию, чтобы сохранить актуальность и актуальность ответов о переполнении стека, вот как я отвечу на вопрос сегодня.

Предпосылка моего первоначального вопроса несколько ошибочна.Причиной использования pimpl-idiom является скрытие деталей реализации от компилятора.Это делается путем сохранения реализации через непрозрачный указатель (указатель на объявленный, но не определенный тип данных).Это может значительно уменьшить количество заголовков, необходимых другим модулям компиляции, которые взаимодействуют с классом и, таким образом, ускоряют время компиляции.В случае шаблона в моем вопросе требуется, чтобы тип T был полностью известен в момент создания экземпляра, что на практике требует, чтобы тип impl был полностью определен везде, где используется C<ImplType>, что явно не является примером pimpl.-idiom в классическом понимании этого термина.

Существуют и другие причины для хранения данных классов с помощью частного указателя, например, это позволяет легко реализовать перемещение и обмен без бросков, а также хорошо, если вашкласс должен выполнять строгую гарантию исключений (см. идиому копирования и обмена Что такое идиома копирования и обмена? ).С другой стороны, он добавляет слой косвенности (часто приводящий к отсутствию кэша) при каждом доступе к impl и распределению / освобождению кучи при создании и уничтожении impl.Это может быть существенное снижение производительности, поэтому это решение не следует считать серебряной пулей.

Если вы можете использовать C ++ 11, тогда вместо boost :: scoped_ptr следует использовать std :: unique_ptr.

1 голос
/ 05 декабря 2011

boost::shared_ptr не требует полного определения, кроме как в точка инстанцирования - в конструкторе, в случае Pimpl. boost::shared_ptr не подходит для идиомы pimpl, однако, так как это дает очень неожиданную семантику (ссылочная семантика для назначения или копирования); если вы действительно хотите дополнительную сложность умный указатель, boost::scoped_ptr будет более подходящим (но это действительно требует полного определения в точке его деструктора проиллюстрированный).

Что касается шаблонов, то нет смысла использовать идиому pimpl для Подробности реализации из шапки. В отсутствие export, все детали реализации шаблона класса должны быть включены везде шаблон используется, поэтому мотивация за pimpl идиома перестает существовать.

...