Ответ 1
A shared_ptr
может быть объявлен с неполным типом, да. Тип не должен быть полным, пока вы не инициализируете его или reset.
Когда вы инициализируете или reset a shared_ptr
, чтобы указать на новый объект, он создает "deleter", который может быть использован для уничтожения объекта. Например, рассмотрим следующее:
// somewhere where A is incomplete:
std::shared_ptr<class A> p;
// define A
class A { /* ... */ };
p.reset(new A());
Когда вы вызываете reset
, A
завершается, потому что вы создаете его экземпляр с помощью new
. Функция reset
создает и хранит внутренне дебетер, который будет использоваться для уничтожения объекта с помощью delete
. Поскольку A
здесь завершен, delete
выполнит правильные действия.
Таким образом, shared_ptr
не требует завершения A
при объявлении shared_ptr<A>
; для этого требуется, чтобы A
был завершен, когда вызывается конструктор shared_ptr
, который принимает необработанный указатель, или когда вы вызываете reset
с необработанным указателем.
Обратите внимание, что если A
не является полным, если вы выполняете одну из этих двух вещей, shared_ptr
не будет делать правильные вещи, а поведение undefined (это объясняется в документация для boost::shared_ptr
, которая, вероятно, является лучшим ресурсом для обучения правильному использованию shared_ptr
, независимо от того, какую версию shared_ptr
вы используете (Boost, TR1, С++ 0x и т.д.)).
Однако, если вы всегда придерживаетесь лучших методов использования для shared_ptr
- особенно, если вы всегда инициализируете и reset a shared_ptr
напрямую с указателем, вызванным вызовом new
- вы не придется беспокоиться о нарушении этого правила.
Эта функция не бесплатна: shared_ptr
должен создать и сохранить указатель на функтор удаления; обычно это делается путем хранения делетера как части блока, который хранит сильные и слабые подсчеты ссылок или путем указания указателя как части этого блока, который указывает на делетера (поскольку вы можете предоставить свой собственный дебетер).
auto_ptr
(и unique_ptr
тоже) предназначен для того, чтобы быть свободным от каких-либо накладных расходов: операции над ним должны быть столь же эффективными, как использование немого указателя. Таким образом, auto_ptr
не имеет этой функции.