19

当尝试将 anauto_ptr与使用前向声明声明的类型一起使用时,如下所示:

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

的析构函数A没有被调用(显然,因为auto_ptr内部deletes 底层指针和不完整类型的析构函数不能被调用)。

但是,相同的代码可以正常工作,并且在使用std::shared_ptr而不是std::auto_ptr. 这怎么解释?

4

1 回答 1

35

Ashared_ptr可以用不完整的类型声明,是的。在初始化或重置类型之前,该类型不需要是完整的。

当您初始化或重置 ashared_ptr以指向一个新对象时,它会创建一个可用于销毁该对象的“删除器”。例如,考虑以下情况:

// somewhere where A is incomplete:
std::shared_ptr<class A> p;

// define A
class A { /* ... */ };

p.reset(new A());

当您调用 时resetA就完成了,因为您正在使用创建它的实例new。该reset函数在内部创建并存储一个删除器,该删除器将用于使用delete. 因为A在这里是完整的,那delete将做正确的事情。

通过这样做,shared_ptr不需要A在声明时完成shared_ptr<A>;它只要求在调用带有原始指针Ashared_ptr构造函数或使用原始指针调用时完成reset

请注意,当您执行这两件事之一时,如果未完成,A不会shared_ptr做正确的事情并且行为未定义(这在文档中进行了boost::shared_ptr解释,这可能是学习如何shared_ptr正确使用的最佳资源,无论您正在使用哪个版本shared_ptr(Boost、TR1、C++0x 等))。

但是,只要您始终遵循 -- 的最佳使用实践,shared_ptr尤其是,如果您始终shared_ptr使用调用 -- 产生的指针直接初始化和重置 a,您new就不必担心违反此规则。

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

auto_ptrunique_ptr也是)被设计为没有任何开销:对其进行的操作应该与使用哑指针一样有效。因此,auto_ptr没有这个功能。

于 2011-04-09T17:59:17.973 回答