1.46、weak_ptr是怎么实现的?

实现原理

控制块(Control Block)

shared_ptrweak_ptr都指向同一个控制块,该控制块维护两个计数器:

  • • 强引用计数(use_count):当前有多少个shared_ptr实例拥有对象所有权。
  • • 弱引用计数(weak_count):当前有多少个weak_ptr实例引用该控制块(不拥有对象所有权)。

对象生命周期管理

  • • 当shared_ptr的最后一个实例销毁时,强引用计数归零,对象被释放。
  • • 控制块本身只有当强引用计数和弱引用计数都为零时才被销毁。

weak_ptr不拥有对象

weak_ptr仅持有对控制块的弱引用,不增加强引用计数,不影响对象生命周期。
它可以观察对象是否还存活,但不控制对象销毁。

关键方法与行为

构造和赋值

  • • weak_ptr可以从shared_ptr构造,内部增加弱引用计数。
  • • 复制或赋值weak_ptr也会增加弱引用计数。

检测对象有效性

  • • expired():判断对象是否已被销毁(即强引用计数是否为0)。
  • • use_count():返回当前强引用计数。

获取临时所有权

  • • lock():尝试从weak_ptr获得一个临时的shared_ptr,如果对象仍然存在(强引用计数>0),返回有效的shared_ptr;否则返回空指针。
  • • lock()操作是线程安全的,保证在多线程环境下不会产生竞态条件。

作用与优势

解决循环引用

在两个对象互相持有shared_ptr时,会导致引用计数永远不为零,造成内存泄漏。
使用weak_ptr打破循环引用链,避免资源无法释放。

避免悬挂指针

通过weak_ptr观察对象状态,避免访问已被销毁的对象,减少悬挂指针风险。

线程安全的临时访问

多线程环境下,weak_ptr能安全地检测对象是否存活并获取临时所有权。

简要示意图

shared_ptr<T> ---+
                 | 控制块(use_count, weak_count)
weak_ptr<T> -----+

- use_count:shared_ptr数量
- weak_count:weak_ptr数量(不含shared_ptr)

总结

std::weak_ptr通过共享控制块中的弱引用计数实现对对象的非拥有性观察,避免循环引用导致的内存泄漏,并提供线程安全的方式获取临时所有权。它是shared_ptr的辅助工具,适用于需要观察对象生命周期但不参与所有权管理的场景。
本文首发于【讳疾忌医-note】公众号,未经授权,不得转载。
(加入我的知识星球,免费获取账号,解锁所有文章。)

阅读剩余
THE END