引自C ++ Primer $ 12.1.6:
weak_ptr
(表12.5)是一个智能指针,不能控制生命周期 它指向的对象。相反,weak_ptr指向由其管理的对象 一个shared_ptr
。将weak_ptr绑定到shared_ptr 不会更改 引用计数shared_ptr
。一旦最后shared_ptr
指向 对象消失,对象本身将被删除。 即使是,该对象也将被删除 有weak_ptrs
指向它 - 因为名称weak_ptr
,它捕获了 认为weak_ptr
分享其对象“弱”。
但是,我读过article说:
使用make_shared更有效率。 shared_ptr实现必须将管理信息保存在由引用给定对象的所有shared_ptrs和weak_ptrs共享的控制块中。特别是,该管家信息不仅包括一个而且包括两个参考计数:
“强引用”计数用于跟踪当前使对象保持活动状态的shared_ptrs数。当最后一个强引用消失时,共享对象被销毁(并可能被解除分配)。
- 醇>
“弱引用”计数用于跟踪当前正在观察对象的weak_ptrs的数量。 当最后一个弱引用消失时,共享内务控制块被销毁并解除分配(并且如果共享对象尚未释放,则会解除分配)。
据我所知,shared_ptr
创建的make_shared
与这些引用计数在同一control block内。因此,对象直到最后{{1}才会被释放过期。
weak_ptr
实际上会影响该对象的生命周期。 weak_ptr
需要跟踪它的弱引用?weak_ptr可以通过检查控制块中的强引用来判断对象是否存在,所以我认为控制块没有需要跟踪弱参考。 只是出于好奇,shared_ptr
创建的控制块是什么样的?是这样的:
shared_ptr
答案 0 :(得分:15)
引用计数控制指向对象的生命周期。弱计数不会,但 控制(或参与控制)控制块的生命周期。
如果引用计数转到0
,则对象已销毁,但不一定已取消分配。当弱计数转到0
时(或当引用计数转到0
时,如果发生这种情况时没有weak_ptr
),则控制块将被销毁并取消分配,并且如果对象的存储空间尚未释放,则将其解除分配。
销毁和解除分配指向对象之间的分离是一个您不需要关心的实现细节,但它是由使用{{ 1}}。
如果你这样做
make_shared
为shared_ptr<int> myPtr(new int{10});
分配存储空间,然后将其传递给int
构造函数,该构造函数分别为控制块分配存储空间。在这种情况下,shared_ptr
的存储空间可以尽快解除分配:一旦引用计数达到int
,即使仍然存在弱计数。
如果你这样做
0
然后auto myPtr = make_shared<int>(10);
可能会执行优化,它会一次性为make_shared
和控制块分配存储空间。这意味着在控制块的存储也可以解除分配之前,不能释放int
的存储空间。 int
的生命周期在引用计数达到int
时结束,但在弱计数达到0
之前,其存储空间不会被释放。
现在清楚了吗?
答案 1 :(得分:5)
weak_ptr需要指向可以判断对象是否存在的东西,因此它知道它是否可以转换为shared_ptr。因此,需要一个小物体来保存这些信息。
当删除最后一周的day_ptr(或shared_ptr)时,需要销毁此内务控制块。因此,它必须保持shared_ptr和week_ptr的计数。
请注意,管家控制块与ptr指向的对象不同,因此week_ptr不会影响对象的生命周期。
根据您希望的行为,有许多不同的方法来实现智能指针。如果你想了解更多,我会推荐&#34;现代C ++设计&#34;由Alexandrescu(https://www.amazon.com/Modern-Design-Generic-Programming-Patterns/dp/0201704315)
答案 2 :(得分:2)
weak_ptr和shared_ptr都指向包含控制块的内存。如果在shared_ptr计数器达到0后立即删除控制块(但弱计数器没有),则会留下指向垃圾内存的weak_ptrs。然后当你尝试使用weak_ptr时,它会读取释放的内存并发生坏事(UB)。
由于这个原因,只要任何weak_ptr可能试图读取它,控制块必须保持活动状态(分配和构造,不销毁或解除分配)。
主(指向)对象将被销毁,并且一旦共享计数器达到0,可能(希望)被解除分配。当两个计数器都达到0时,控制块将被销毁并解除分配。
答案 3 :(得分:0)
一个不错的第一步是在头脑中对该概念的表象清楚,使销毁和解除分配之间的区别更加明显。是一种不需要您关心的(详细提到的)无知强化步骤的详细信息。
因此,假设 SeriousObject
为 class
,其大小约为系统内存的一半,并且在构造时可以控制鼠标,并且我们认为这是被破坏的隐性副作用,而不是 SeriousObject
的解除分配 实例 。在这种情况下,尽管鼠标控件返回了,但您仍然只有一半的可用内存。最坏的情况是,在代码的某个地方存在被遗忘甚至泄漏的更严重的地方, weak_ptr
,使您的记忆变得la脚,情绪低落,并且在其余的情况下显示了50%的剩余量执行。但是,嘿,至少它没有泄漏,对吧?
我假设您在每个问题上都负有责任:
weak_ptr
,而 shared_ptr
和控制块均已被破坏,并且至少有一个 weak_ptr
指向 object
,您认为在 {{1} } 尝试按照您的建议检查控制块中的 strong参考? ...到处都是偏头痛。PS(实际上更像是BTW)
我个人的困惑不在于 weak_ptr
,而是决定在对象生命周期的特定阶段进行这种优化,我指的是一次分配类型优化并进行详细说明,我的意思是选择优化最短,单次出现的寿命阶段,同时接受以技术和行为方面的副作用为代价付出的代价,而作为交换,他们实际上却毫不费力地收拾了几只山羊粪便,作为其劳动成果。 Pff