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

发布于 2024-10-31 11:59:06 字数 312 浏览 1 评论 0原文

当尝试使用带有前向声明的类型的 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 deletes 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

香草可樂 2024-11-07 11:59:06

可以用不完整的类型声明 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 时,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:

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

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

p.reset(new A());

When you call reset, A is complete because you're creating an instance of it using new. The reset function creates and stores internally a deleter that will be used to destroy the object using delete. Because A is complete here, that delete will do the right thing.

By doing this, shared_ptr does not require that A be complete when the shared_ptr<A> is declared; it only requires that A is complete when the shared_ptr constructor that takes a raw pointer is invoked or when you call reset 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 for boost::shared_ptr, which is probably the best resource for learning how to use shared_ptr correctly, regardless which version of shared_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 a shared_ptr directly with a pointer resulting from a call to new--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 (and unique_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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文