A shared_ptr
может быть объявлено с неполным типом, да.Тип не обязательно должен быть завершен до тех пор, пока вы не инициализируете или не сбросите его.
Когда вы инициализируете или сбрасываете shared_ptr
для указания на новый объект, он создает «удалитель», который можно использовать для уничтожения объекта.объект.Например, рассмотрим следующее:
// 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
не будет делать правильные вещи, и поведение не определено (это объясняется в документация для boost::shared_ptr
, которая, вероятно, является лучшим ресурсом для обучения правильному использованию shared_ptr
, независимо от того, какую версию shared_ptr
вы используете (Boost, TR1, C ++ 0x и т. Д..)).
Однако, если вы всегда следуете лучшим рекомендациям по использованию shared_ptr
, особенно если вы всегда инициализируете и сбрасываете shared_ptr
напрямую с указателем, полученным в результате вызова new
- вам не придется беспокоиться о нарушении этого правила.
Эта функция не бесплатна: shared_ptr
должен создавать и хранить указатель на функтор удаления;как правило, это делается путем сохранения средства удаления как части блока, в которой хранятся счетчики сильных и слабых ссылок, или с помощью указателя в качестве части этого блока, который указывает на средство удаления (поскольку вы можете предоставить свой собственный средство удаления).
auto_ptr
(и unique_ptr
тоже) разработаны без лишних затрат: операции с ним должны быть такими же эффективными, как использование тупого указателя.Таким образом, auto_ptr
не имеет этой функциональности.