weak_ptr如何工作?

| 我了解如何使用
weak_ptr
shared_ptr
。通过计算对象中引用的数量,我了解ѭ1的工作原理。
weak_ptr
如何工作?我尝试阅读Boost的源代码,但我对Boost没有足够的了解,无法理解Boost的所有用途。 谢谢。     
已邀请:
shared_ptr
使用额外的“计数器”对象(又名“共享计数”或“控制块”)来存储参考计数。 (顺便说一句:\“ counter \”对象也存储删除器。) 每个
shared_ptr
weak_ptr
都包含指向实际指针的指针,以及指向\“ counter \”对象的第二个指针。 为了实现“ 0”,\“ counter \”对象存储两个不同的计数器: “使用计数”是指向该对象的ѭ1个实例的数量。 \“弱计数\”是指向该对象的ѭ0个实例的数量,如果\“使用计数\”仍大于0,则加1。 当“使用计数”达到零时,将删除指针。 当“弱计数”达到零时,将删除“计数器”辅助对象(这意味着“使用计数”也必须为零,请参见上文)。 当您尝试从“ 0”中获得“ 1”时,库会自动检查“使用计数”,如果它大于0,则将其递增。如果成功了,您将获得
shared_ptr
。如果\“使用计数\”已经为零,则会得到一个空的
shared_ptr
实例。 编辑:现在,为什么当两个计数都下降到零时,为什么不将\“ counter \”对象释放给弱计数呢?好问题。 另一种方法是,当“使用计数”和“弱计数”都降为零时,删除“计数器”对象。这是第一个原因:不可能在每个平台上原子地检查两个(指针大小的)计数器,即使在任何地方,它也比仅检查一个计数器更为复杂。 另一个原因是删除程序必须保持有效,直到完成执行。由于删除程序存储在\“ counter \”对象中,这意味着\“ counter \”对象必须保持有效。考虑如果某个对象有一个“ 1”和一个“ 0”,并且在并发线程中同时重置它们,会发生什么情况。假设ѭ1排名第一。它将“使用计数”减小为零,并开始执行删除程序。现在,“ 0”将“弱计数”减小为零,并且发现“使用计数”也为零。因此它删除\“ counter \”对象,并删除它。删除程序仍在运行时。 当然,可以采用多种方法来确保“计数器”对象保持活动状态,但是我认为将“弱计数”增加一个是一种非常优雅且直观的解决方案。 \“弱计数\”成为\“计数器\”对象的引用计数。而且由于“ 1”也引用了计数器对象,因此它们也必须增加“弱计数”。 一个可能甚至更直观的解决方案是为每个单个“ 1”增加“弱计数”,因为每个单个“ 1”都持有对“ counter”对象的引用。 为所有“ 1”实例添加一个只是一种优化(在复制/分配“ 1”实例时节省一个原子增量/减量)。     
基本上,\“ weak_ptr \”是普通的\“ T * \”指针,可让您稍后在代码中恢复强引用,即\“ shared_ptr \”。 就像普通的T *,weak_ptr不会执行任何引用计数。在内部,为了支持对任意类型T的引用计数,STL(或实现这种逻辑的任何其他库)创建了一个包装器对象,我们将其称为“ Anchor”。 \“ Anchor \”仅用于实现引用计数,而我们需要的“当计数为零时,调用delete”行为。 在一个有力的参考中,shared_ptr实现了其副本,operator =,构造函数,析构函数以及其他相关的API,以更新\“ Anchor \” \的参考计数。这就是shared_ptr如何确保您的\“ T \”的寿命与某人正在使用的时间一样长。在\“ weak_ptr \”中,这些相同的API只是复制实际的Anchor ptr。他们不会更新参考计数。 这就是为什么\“ weak_ptr \”最重要的API是\“ expired \”和名称不正确的\“ lock \”的原因。 \“ Expired \”告诉您基础对象是否仍然存在,即\“由于所有强引用都超出范围,它已经被删除了吗?\”。 \“ Lock \”(如果可以)会将“ weak_ptr”转换为强引用“ shared_ptr”,从而恢复引用计数。 顺便说一句,\“ lock \”是该API的可怕名称。您不是(只是)调用一个互斥锁,而是从一个弱引用创建一个强引用,而该“锚”起作用。这两个模板中的最大缺陷是它们没有实现operator->,因此对对象执行任何操作都必须恢复原始\“ T * \”。他们这样做主要是为了支持\“ shared_ptr \”之类的事情,因为基本类型不支持\“-> \”运算符。     

要回复问题请先登录注册