Удаление указателя на неполный тип и интеллектуальных указателей

при попытке использовать auto_ptr С типом, который был объявлен с forward-declaration, например:

class A;
...
std::auto_ptr<A> a;

деструктор A не называется (видимо, потому что auto_ptr внутри deletes базовый указатель и деструктор для неполного типа не могут быть вызваны).

однако тот же код работает нормально, и деструктор вызывается при использовании std::shared_ptr вместо std::auto_ptr. Как это можно объяснить?

1 ответов


A shared_ptr может быть объявлено с неполным типом, да. Этот тип не должен быть завершен до его инициализации или сброса.

при инициализации или сброса 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. The reset функция создает и сохраняет внутри deleter, который будет использоваться для уничтожения объекта с помощью delete. Потому что A - это здесь, что delete будет делать правильные вещи.

при этом, shared_ptr не требуется A быть полным, когда shared_ptr<A> объявлено; для этого требуется только A завершается, когда shared_ptr конструктор, который принимает необработанный указатель вызывается или при вызове reset С необработанного указателя.

обратите внимание, что если A is не завершить, когда вы делаете одну из этих двух вещей,shared_ptr не будет делать правильную вещь, и поведение не определено (это объясняется в документация boost::shared_ptr, который, вероятно, является лучшим ресурсом для обучения использованию shared_ptr правильно, независимо от того, какая версия shared_ptr вы используете (Boost, TR1, C++0x и т. д.)).

однако, если вы всегда следуете лучшим методам использования для shared_ptr--особенно, если вы всегда инициализировать и сброс shared_ptr непосредственно с указателем, полученным в результате вызова new - вы не должны беспокоиться о нарушении этого правила.

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

auto_ptrunique_ptr too) разработан, чтобы быть свободным от каких-либо накладных расходов: операции на нем должны быть так же эффективны, как и использование немого указателя. Таким образом, auto_ptr не имеет этой функции.