weak_ptr用于解决shared_ptr的循环引用问题,示例中A和B互相持有shared_ptr导致内存泄漏,将其中一个改为weak_ptr后打破循环,引用计数正常归零,对象可析构,weak_ptr通过lock()安全访问目标,常用于父子节点等场景。

在 C++ 中,weak_ptr 主要用于解决 shared_ptr 可能引起的循环引用问题。当两个或多个对象通过 shared_ptr 相互持有对方时,引用计数永远无法归零,导致内存泄漏。weak_ptr 不增加引用计数,仅观察对象是否存在,因此适合打破这种循环。
循环引用问题示例
考虑两个类 A 和 B,它们互相持有对方的 shared_ptr:
#include #include struct B; // 前向声明struct A { std::shared_ptr b_ptr; ~A() { std::cout << "A 被销毁n"; }};struct B { std::shared_ptr a_ptr; ~B() { std::cout << "B 被销毁n"; }};int main() { auto a = std::make_shared(); auto b = std::make_shared(); a->b_ptr = b; b->a_ptr = a; std::cout << "a 引用计数: " << a.use_count() << "n"; // 输出 2 std::cout << "b 引用计数: " << b.use_count() << "n"; // 输出 2 return 0;}
程序结束时,A 和 B 的析构函数都不会被调用。因为 a 和 b 的引用计数都是 2(外部变量 + 对方持有),离开作用域后引用计数变为 1,无法释放。
使用 weak_ptr 打破循环
修改其中一个引用为 weak_ptr,可打破循环。通常“从属”或“反向”引用使用 weak_ptr。
struct A { std::shared_ptr b_ptr; ~A() { std::cout << "A 被销毁n"; }};struct B { std::weak_ptr a_ptr; // 改为 weak_ptr ~B() { std::cout << "B 被销毁n"; }};
此时 main 函数中:
a 的引用计数:1(仅由 main 中的变量持有) b 的引用计数:2(main 持有 + a 持有)
当 main 结束时,a 和 b 的 shared_ptr 被释放,引用计数归零,对象正常析构。
weak_ptr 的安全访问
使用 weak_ptr 时,不能直接访问对象,必须先转为 shared_ptr:
void check_A(std::weak_ptr &wp) { if (auto sp = wp.lock()) { // 对象仍存在,sp 是临时 shared_ptr std::cout << "A 仍然存在n"; } else { std::cout << "A 已被释放n"; }}
lock() 返回 shared_ptr,若对象已销毁则返回空。这保证了线程安全和生命周期管理。
基本上就这些。weak_ptr 不参与所有权,只观察,是打破 shared_ptr 循环引用的标准做法。常见于父子节点、观察者模式、缓存等场景。不复杂但容易忽略,用对了能避免内存泄漏。
以上就是weak_ptr在什么场景使用 打破循环引用实际案例的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1472384.html
微信扫一扫
支付宝扫一扫