我了解如何使用 weak_ptr
和 shared_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_ptr
和weak_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,则加一.shared_ptr
instances pointing to the object.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_ptr
s 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 是如何工作的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!