shared_ptr循环引用的本质是双方互相持有导致引用计数无法归零,典型场景包括双向链表、父子对象和观察者模式;weak_ptr通过不增加引用计数并配合lock()安全访问来打破循环。
当两个对象各自用shared_ptr持有对方时,引用计数永远无法归零,导致内存泄漏。最常见于双向链表节点、父子对象(如树结构中父指针和子指针互相持有时)、观察者模式中观察者与被观察者互相强引用。
weak_ptr不增加引用计数,只“观察”所指向对象是否还存在。它不能直接访问对象,必须通过lock()升级为shared_ptr——成功则说明对象仍存活,失败(返回空)则说明已被释放。
额外同步),但其指向的对象生命周期仍需逻辑保证假设Parent持有children的shared_ptr,Child需反向访问Parent但不延长其生命周期:
struct Parent;
struct Child {
std::weak_ptr parent; // 不参与所有权
void doSomething() {
auto p = parent.lock(); // 尝试获取临时shared_ptr
if (p) {
p->doWork(); // 安全调用
} else {
// Parent已被销毁,做清理或跳过
}
}
};
struct Parent {
std::vector> children;
void addChild() {
auto c = std::make_shared();
c->parent = shared_from_this(); // weak_ptr自动绑定当前shared_ptr
children.push_back(c);
}
};
除了weak_ptr,还可结合设计层面规避:
weak_ptr不是万能胶,核心在于厘清谁是真正的所有者,让非所有者“弱观察”。用对了,循环引用就自然解开。