Удаление указателя на неполный тип и интеллектуальных указателей
при попытке использовать auto_ptr
С типом, который был объявлен с forward-declaration, например:
class A;
...
std::auto_ptr<A> a;
деструктор A
не называется (видимо, потому что auto_ptr
внутри delete
s базовый указатель и деструктор для неполного типа не могут быть вызваны).
однако тот же код работает нормально, и деструктор вызывается при использовании 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_ptr
(и unique_ptr
too) разработан, чтобы быть свободным от каких-либо накладных расходов: операции на нем должны быть так же эффективны, как и использование немого указателя. Таким образом, auto_ptr
не имеет этой функции.