删除指向不完整类型和智能指针的指针

时间:2011-04-09 17:50:42

标签: c++ c++11 shared-ptr smart-pointers auto-ptr

尝试使用带有forward-declaration声明的类型的auto_ptr时,如下所示:

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

未调用A的析构函数(显然,因为auto_ptr内部delete是底层指针,并且不能调用不完整类型的析构函数。

但是,相同的代码工作正常,并且在使用std::shared_ptr而不是std::auto_ptr时会调用析构函数。 怎么解释?

1 个答案:

答案 0 :(得分:35)

可以使用不完整的类型声明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将无法执行正确的操作并且行为未定义(这是在the documentation for boost::shared_ptr中解释,这可能是学习如何正确使用shared_ptr的最佳资源,无论您使用的是哪个版本的shared_ptr(Boost,TR1,C ++ 0x等)。 ))。

但是,只要您始终遵循shared_ptr的最佳使用惯例 - 值得注意的是,如果您始终使用指向{{1}的调用产生的指针直接初始化并重置shared_ptr - 你不必担心违反这条规则。

此功能不是免费的:new必须创建并存储指向删除器仿函数的指针;通常这是通过将删除器存储为存储强弱引用计数的块的一部分,或者通过将指针作为指向删除器的块的一部分来存储(因为您可以提供自己的删除器)。

shared_ptr(和auto_ptr也被设计为没有任何开销:对它的操作应该与使用哑指针一样有效。因此,unique_ptr没有此功能。