shared_ptr / weak_ptr 为什么会有循环引用问题? 一、先一句话结论先抓本质shared_ptr 循环引用问题本质是引用计数永远不为 0导致对象无法释放二、先搞清楚 shared_ptr 的本质std::shared_ptrA p1 std::make_sharedA(); std::shared_ptrA p2 p1;内部模型你必须知道对象 A ↑ 控制块control block - 引用计数 2 每多一个 shared_ptr引用计数 1 每销毁一个引用计数 -1 当引用计数 0 → delete 对象三、问题来了循环引用看这个经典例子class B; class A { public: std::shared_ptrB b; }; class B { public: std::shared_ptrA a; };创建关系auto a std::make_sharedA(); auto b std::make_sharedB(); a-b b; b-a a;四、发生了什么关键a → bb → a引用计数情况a.count 2 main b-a b.count 2 main a-b当 main 结束a.count 1b.count 1永远不会变成 0五、结果内存泄漏A 和 B 都不会被释放六、本质原因必须理解shared_ptr 是“强引用”会增加引用计数而A 持有 BB 持有 A 形成引用环reference cycle七、解决方案weak_ptrweak_ptr 是“弱引用”不会增加引用计数八、改造代码标准解法class B; class A { public: std::shared_ptrB b; }; class B { public: std::weak_ptrA a; // ⭐ 改这里 };九、现在发生什么a → b强引用b → a弱引用引用计数a.count 1b.count 1 main 结束count → 0对象正常释放 ✔十、weak_ptr 怎么用重点std::weak_ptrA wp; 不能直接用必须 lock()if (auto sp wp.lock()) { // sp 是 shared_ptr可以安全使用 } 如果对象已经释放lock() 返回 nullptr十一、你必须理解的核心区别类型是否增加引用计数是否控制生命周期shared_ptr✅✅weak_ptr❌❌十二、你要建立的完整模型非常重要shared_ptr 强 ownership负责生命周期 weak_ptr 弱引用观察者十三、工程级理解这才是重点你以后写代码要这样想什么时候用 shared_ptr需要“共享 ownership”的时候什么时候用 weak_ptr避免循环引用 / 观察对象但不拥有十四、经典场景你一定会遇到1️⃣ 双向关系父 → 子shared_ptr 子 → 父weak_ptr2️⃣ 观察者模式Subject 持有 weak_ptrObserver3️⃣ 缓存系统weak_ptr 监控对象是否还存在十五、面试标准回答直接背Q为什么 shared_ptr 会有循环引用问题因为 shared_ptr 使用引用计数管理生命周期当对象之间相互持有 shared_ptr 时会形成引用环导致引用计数无法归零从而产生内存泄漏。Q如何解决使用 weak_ptr 打破循环引用因为 weak_ptr 不增加引用计数。十六、你现在的认知闭环我帮你收一下RAII自动释放 ↓ unique_ptr唯一所有权 ↓ move转移所有权 ↓ shared_ptr共享所有权 ↓ weak_ptr打破循环十七、给你一句“终极理解”必须记shared_ptr 管理生命周期weak_ptr 观察生命周期下一篇《shared_ptr 控制块到底是什么源码级理解》control block 结构引用计数 弱引用计数为什么性能不如 unique_ptr原子操作开销