weak_ptr 是如何工作的? [英] How does weak_ptr work?

查看:25
本文介绍了weak_ptr 是如何工作的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我了解如何使用 weak_ptrshared_ptr.我通过计算其对象中的引用数量来了解 shared_ptr 是如何工作的.weak_ptr 如何工作?我尝试通读 boost 源代码,但我对 boost 不够熟悉,无法理解它使用的所有内容.

I understand how to use weak_ptr and shared_ptr. I understand how shared_ptr works, by counting the number of references in its object. How does weak_ptr work? I tried reading through the boost source code, and I'm not familiar enough with boost to understand all the things it uses.

谢谢.

推荐答案

shared_ptr 使用额外的计数器"对象(又名共享计数"或控制块")来存储引用计数.(顺便说一句:那个计数器"对象也存储了删除器.)

shared_ptr uses an extra "counter" object (aka. "shared count" or "control block") to store the reference count. (BTW: that "counter" object also stores the deleter.)

每个shared_ptrweak_ptr 都包含一个指向实际指针的指针,以及一个指向计数器"对象的第二个指针.

Every shared_ptr and weak_ptr contains a pointer to the actual pointee, and a second pointer to the "counter" object.

为了实现weak_ptr,counter"对象存储了两个不同的计数器:

To implement weak_ptr, the "counter" object stores two different counters:

  • 使用计数"是指向对象的 shared_ptr 实例的数量.
  • 弱计数"是指向对象的 weak_ptr 实例的数量,如果使用计数"仍然 > 0,则加一.
  • The "use count" is the number of shared_ptr instances pointing to the object.
  • The "weak count" is the number of weak_ptr instances pointing to the object, plus one if the "use count" is still > 0.

当使用计数"达到零时删除指针.

The pointee is deleted when the "use count" reaches zero.

当弱计数"达到零(这意味着使用计数"也必须为零,见上文)时,计数器"辅助对象被删除.

The "counter" helper object is deleted when the "weak count" reaches zero (which means the "use count" must also be zero, see above).

当您尝试从 weak_ptr 获取 shared_ptr 时,库会自动检查使用计数",如果它 > 0,则增加它.如果成功,您将获得 shared_ptr.如果使用计数"已经为零,您会得到一个空的 shared_ptr 实例.

When you try to obtain a shared_ptr from a weak_ptr, the library atomically checks the "use count", and if it's > 0 increments it. If that succeeds you get your shared_ptr. If the "use count" was already zero you get an empty shared_ptr instance instead.

编辑:现在,当两个计数都降为零时,为什么他们在弱计数上加一,而不是仅仅释放计数器"对象?好问题.

EDIT: Now, why do they add one to the weak count instead of just releasing the "counter" object when both counts drop to zero? Good question.

另一种方法是在使用计数"和弱计数"都降为零时删除计数器"对象.这是第一个原因:不可能在每个平台上以原子方式检查两个(指针大小的)计数器,即使在任何平台上,它也比只检查一个计数器复杂.

The alternative would be to delete the "counter" object when both the "use count" and the "weak count" drop to zero. Here's the first reason: Checking two (pointer sized) counters atomically is not possible on every platform, and even where it is, it's more complicated than checking just one counter.

另一个原因是删除器必须保持有效直到它完成执行.由于删除器存储在计数器"对象中,这意味着计数器"对象必须保持有效.考虑如果某个对象有一个 shared_ptr 和一个 weak_ptr 会发生什么,并且它们在并发线程中同时被重置.假设 shared_ptr 首先出现.它将使用计数"减少到零,并开始执行删除器.现在 weak_ptr 将弱计数"减少到零,并且发现使用计数"也为零.所以它删除了计数器"对象,并删除了删除器.当删除程序仍在运行时.

Another reason is that the deleter must stay valid until it has finished executing. Since the deleter is stored in the "counter" object, that means the "counter" object must stay valid. Consider what could happen if there is one shared_ptr and one weak_ptr to some object, and they are reset at the same time in concurrent threads. Let's say the shared_ptr comes first. It decreases the "use count" to zero, and begins executing the deleter. Now the weak_ptr decreases the "weak count" to zero, and finds the "use count" is zero as well. So it deletes the "counter" object, and with it the deleter. While the deleter is still running.

当然会有不同的方法来确保计数器"对象保持活动状态,但我认为将弱计数"增加一个是一个非常优雅和直观的解决方案.弱计数"成为计数器"对象的引用计数.由于 shared_ptr 也引用了计数器对象,因此它们也必须增加弱计数".

Of course there would be different ways to assure that the "counter" object stays alive, but I think increasing the "weak count" by one is a very elegant and intuitive solution. The "weak count" becomes the reference count for the "counter" object. And since shared_ptrs reference the counter object too, they too have to increment the "weak count".

一个可能更直观的解决方案是为每个 shared_ptr 增加弱计数",因为每个 shared_ptr 都持有对计数器"对象的引用.

A probably even more intuitive solution would be to increment the "weak count" for every single shared_ptr, since every single shared_ptr hold's a reference to the "counter" object.

为所有 shared_ptr 实例添加一个只是一种优化(在复制/分配 shared_ptr 实例时节省一个原子增量/减量).

Adding one for all shared_ptr instances is just an optimization (saves one atomic increment/decrement when copying/assigning shared_ptr instances).

这篇关于weak_ptr 是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆