Итак, мне интересно, эта техника действительно используется на практике?Я должен использовать это везде, или с осторожностью?
Конечно, это используется.Я использую это в своем проекте, почти в каждом классе.
Причины использования языка PIMPL:
Бинарная совместимость
При разработке библиотеки вы можете добавлять / изменять поля в XImpl
, не нарушаябинарная совместимость с вашим клиентом (что означает сбой!).Поскольку двоичный макет класса X
не изменяется при добавлении новых полей в класс Ximpl
, безопасно добавлять новые функции в библиотеку при обновлении второстепенных версий.
Конечно, вы можететакже добавьте новые публичные / частные не виртуальные методы в X
/ XImpl
, не нарушая двоичную совместимость, но это на уровне стандартной техники заголовка / реализации.
Скрытие данных
Если вы разрабатываете библиотеку, особенно проприетарную, может быть желательно не раскрывать, какие другие библиотеки / методы реализации использовались для реализации открытого интерфейса вашей библиотеки.Либо из-за проблем с интеллектуальной собственностью, либо из-за того, что вы считаете, что у пользователей может возникнуть соблазн принять опасные предположения о реализации или просто нарушить инкапсуляцию, используя ужасные приемы приведения.PIMPL решает / смягчает это.
Время компиляции
Время компиляции уменьшается, так как только исходный файл (файл реализации) X
необходимо перестраивать при добавлении / удалении полей и / или методов в XImpl
класс (который соответствует добавлению приватных полей / методов в стандартной технике).На практике это обычная операция.
При использовании стандартного метода заголовка / реализации (без PIMPL), когда вы добавляете новое поле в X
, каждый клиент, который когда-либо выделяет X
(либо в стеке,или в куче) необходимо перекомпилировать, потому что он должен корректировать размер выделения.Ну, каждый клиент, который никогда не выделяет X , а также , должен быть перекомпилирован, но это просто накладные расходы (в результате код на стороне клиента будет таким же).
Более тогосо стандартным разделением заголовок / реализация XClient1.cpp
необходимо перекомпилировать, даже когда частный метод X::foo()
был добавлен к X
и X.h
изменен, даже если XClient1.cpp
не может вызвать этот метод по причинам инкапсуляции!Как и выше, это просто накладные расходы и связано с тем, как работают реальные системы сборки C ++.
Конечно, перекомпиляция не требуется, когда вы просто изменяете реализацию методов (потому что вы не трогаете заголовок), но это на одном уровне со стандартной техникой заголовка / реализации.
Рекомендуется ли использовать эту технику во встроенных системах (где производительность очень важна)?
Это зависит от того, насколько сильна ваша цель.Однако единственный ответ на этот вопрос: измерьте и оцените то, что вы получаете и теряете.Также учтите, что если вы не публикуете библиотеку, предназначенную для использования во встроенных системах вашими клиентами, применяется только преимущество времени компиляции!