删除指向不完整类型和智能指针的指针
当尝试使用带有前向声明的类型的 auto_ptr
时,如下所示:
class A;
...
std::auto_ptr<A> a;
A
的析构函数未被调用(显然,因为 auto_ptr< /code> 内部
删除
底层指针,并且无法调用不完整类型的析构函数)。
但是,相同的代码工作正常,并且在使用 std::shared_ptr 而不是 std::auto_ptr 时调用析构函数。 这怎么解释呢?
When trying to use an auto_ptr
with a type that was declared with forward-declaration, like this:
class A;
...
std::auto_ptr<A> a;
the destructor of A
is not called (apparently, because auto_ptr
internally delete
s the underlying pointer and the destructor for an incomplete type cannot be called).
However, the same code works fine and the destructor is called when using std::shared_ptr
instead of std::auto_ptr
.
How can that be explained?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
可以用不完整的类型声明
shared_ptr
,是的。在初始化或重置之前,该类型不需要完整。当您初始化或重置
shared_ptr
以指向新对象时,它会创建一个可用于销毁该对象的“删除器”。例如,请考虑以下情况:当您调用
reset
时,A
已完成,因为您正在使用new
创建它的实例。reset
函数在内部创建并存储一个删除器,该删除器将用于使用delete
销毁对象。因为A
在这里已完成,所以delete
会做正确的事情。通过这样做,在声明
shared_ptr
时,shared_ptr
不要求A
是完整的;它仅要求在调用采用原始指针的shared_ptr
构造函数或使用原始指针调用reset
时完成A
。请注意,如果当您执行这两件事之一时
A
未完成,则shared_ptr
将不会做正确的事情,并且行为未定义(boost 文档对此进行了解释: :shared_ptr,这可能是学习如何正确使用shared_ptr
的最佳资源,无论您使用的是哪个版本的shared_ptr
(Boost、 TR1、C++0x 等))。但是,只要您始终遵循
shared_ptr
的最佳使用实践 - 特别是,如果您始终使用调用shared_ptr
所产生的指针直接初始化和重置shared_ptr
code>new——你不必担心违反这条规则。此功能不是免费的:
shared_ptr
必须创建并存储指向删除器函子的指针;通常,这是通过将删除器存储为存储强引用计数和弱引用计数的块的一部分,或者通过将指针作为指向删除器的块的一部分来完成的(因为您可以提供自己的删除器)。auto_ptr
(以及unique_ptr
)被设计为没有任何开销:对其进行的操作应该与使用哑指针一样高效。因此,auto_ptr
没有此功能。A
shared_ptr
can be declared with an incomplete type, yes. The type does not need to be complete until you initialize or reset it.When you initialize or reset a
shared_ptr
to point to a new object, it creates a "deleter" that can be used to destroy the object. For example, consider the following:When you call
reset
,A
is complete because you're creating an instance of it usingnew
. Thereset
function creates and stores internally a deleter that will be used to destroy the object usingdelete
. BecauseA
is complete here, thatdelete
will do the right thing.By doing this,
shared_ptr
does not require thatA
be complete when theshared_ptr<A>
is declared; it only requires thatA
is complete when theshared_ptr
constructor that takes a raw pointer is invoked or when you callreset
with a raw pointer.Note that if
A
is not complete when you do one of those two things,shared_ptr
won't do the right thing and the behavior is undefined (this is explained in the documentation forboost::shared_ptr
, which is probably the best resource for learning how to useshared_ptr
correctly, regardless which version ofshared_ptr
you are using (Boost, TR1, C++0x, etc.)).However, as long as you always follow the best usage practices for
shared_ptr
--notably, if you always initialize and reset ashared_ptr
directly with a pointer resulting from a call tonew
--you won't have to worry about violating this rule.This functionality isn't free:
shared_ptr
has to create and store a pointer to the deleter functor; typically this is done by storing the deleter as part of the block that stores the strong and weak reference counts or by having a pointer as part of that block that points to the deleter (since you can provide your own deleter).auto_ptr
(andunique_ptr
too) is designed to be free of any overhead: operations on it are supposed to be just as efficient as using a dumb pointer. Thus,auto_ptr
doesn't have this functionality.