Mediumpimpl

Что такое идиома pimpl и зачем нужен явный деструктор в .cpp?

1Постановка

Разберём, что от вас хотят в этом вопросе и как к нему подступиться на собеседовании.

2Решение

При использовании pimpl struct Impl в заголовке — incomplete type (только forward declared). Деструктор unique_ptr<Impl> вызывает delete на Impl*, что требует знания полного типа Impl.

// widget.h
class Widget {
    struct Impl;
    std::unique_ptr<Impl> impl_;  // Impl неполный здесь
public:
    ~Widget();   // объявлен здесь
    Widget(Widget&&) noexcept;    // и move ops тоже
    Widget& operator=(Widget&&) noexcept;
};

// widget.cpp — здесь Impl определён полностью
#include "widget.h"
struct Widget::Impl { /* полные поля */ };
Widget::~Widget() = default;                       // теперь unique_ptr видит ~Impl
Widget::Widget(Widget&&) noexcept = default;
Widget& Widget::operator=(Widget&&) noexcept = default;

Если компилятор сгенерирует деструктор inline в заголовке, он не сможет вызвать ~Impl. Поэтому деструктор (и move ops) выносятся в .cpp. Copy ctor/assign нельзя = default — нужно писать вручную в .cpp.

3Как отвечать

  • Сначала уточните условия и ограничения, покажите аналитическое мышление.
  • Рассуждайте вслух — интервьюеру важен ход мысли, а не только финальный ответ.
  • Оцените сложность по времени и памяти (Big-O), если это алгоритмический вопрос.
💡

На реальном собеседовании Alffert подскажет развёрнутый ответ в реальном времени.