当尝试将 anauto_ptr
与使用前向声明声明的类型一起使用时,如下所示:
class A;
...
std::auto_ptr<A> a;
的析构函数A
没有被调用(显然,因为auto_ptr
内部delete
s 底层指针和不完整类型的析构函数不能被调用)。
但是,相同的代码可以正常工作,并且在使用std::shared_ptr
而不是std::auto_ptr
. 这怎么解释?
当尝试将 anauto_ptr
与使用前向声明声明的类型一起使用时,如下所示:
class A;
...
std::auto_ptr<A> a;
的析构函数A
没有被调用(显然,因为auto_ptr
内部delete
s 底层指针和不完整类型的析构函数不能被调用)。
但是,相同的代码可以正常工作,并且在使用std::shared_ptr
而不是std::auto_ptr
. 这怎么解释?
Ashared_ptr
可以用不完整的类型声明,是的。在初始化或重置类型之前,该类型不需要是完整的。
当您初始化或重置 ashared_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
使用调用 -- 产生的指针直接初始化和重置 a,您new
就不必担心违反此规则。
此功能不是免费的: shared_ptr
必须创建并存储指向删除器函子的指针;通常这是通过将删除器存储为存储强和弱引用计数的块的一部分或通过将指针作为指向删除器的块的一部分来完成的(因为您可以提供自己的删除器)。
auto_ptr
(unique_ptr
也是)被设计为没有任何开销:对其进行的操作应该与使用哑指针一样有效。因此,auto_ptr
没有这个功能。