

新闻资讯
技术百科std::shared_ptr循环引用会导致内存泄漏,因引用计数无法归零;需用std::weak_ptr打破强引用链,其不增引用计数,须通过lock()获取临时shared_ptr访问对象。
当两个 std::shared_ptr 相互持有对方所管理的对象时,引用计数永远无法归零,对象不会被析构 —— 这就是循环引用。它不报错、不崩溃,但内存持续增长,是典型的“静默泄漏”。
std::weak_ptr 打断强引用链std::weak_ptr 不增加引用计数,只“观察”对象是否还活着。它不能直接访问对象,必须通过 lock() 转成 std::shared_ptr 才能使用;若原对象已销毁,lock() 返回空的 std::shared_ptr。
常见做法是:
一方用 std::shared_ptr 拥有另一方,另一方用 std::weak_ptr 回指——比如父类持子类的 std::shared_ptr,子类持父类的 std::weak_ptr。
struct Parent;
struct Child {
std::weak_ptr parent; // 不参与所有权,不增加引用计数
};
struct Parent {
std::shared_ptr child;
};
weak_ptr::lock() 或直接构造std::shared_ptr(parent) 构造(即拷贝构造)会触发未定义行为 —— std::weak_ptr 不能直接转 std::shared_ptr,必须调用 lock()
lock() 返回的是临时 std::shared_ptr,如果只用于条件判断但没保存,后续再访问可能已失效lock() 是安全的,但若此时对象正被销毁(比如 Parent 析构中访问 child->parent.lock()),lock() 会返回空,这是预期行为没有编译期检查,只能靠设计约束和运行时辅助:
use_count() 打印关键节点的引用数(仅 debug 版),比如 ptr.use_count() 看是否异常偏高shared_from_this() 向自己创建循环,尤其在回调注册场景下std::vector<:shared_ptr>>)替代双向链表式结构,减少手动管理指针的必要最麻烦的地方不是写 weak_ptr,而是判断哪边该强、哪边该弱——这取决于对象生命周期的自然归属关系,一旦定错,问题会藏得很深。