C++ shared_ptr处理循环与非循环列表及weak_ptr使用疑问
智能指针循环引用场景的正确实现方案
核心规则
解决循环引用的核心是明确所有权边界:仅用shared_ptr标记「所有权持有」关系,非所有权的反向引用统一使用weak_ptr,避免双向强引用形成计数闭环。
循环列表问题修复
错误尝试原因说明
- 全部
next改为weak_ptr:链表的所有权逻辑是前节点持有后节点的所有权,全改为弱引用后没有强引用持有节点对象,节点创建后会立即被释放,因此出现过早释放的问题。 - 仅将外部head改为
weak_ptr:内部节点之间的循环强引用仍然存在,三个节点的强引用计数始终为1,永远无法触发销毁逻辑,因此内存泄漏。
正确实现方案(二选一即可)
方案1:仅循环位使用弱引用
保持链表「前节点持有后节点强引用」的逻辑,仅将尾节点指向头节点的循环引用改为weak_ptr,同时外部持有头节点的shared_ptr作为整个链表的所有者。如果需要兼容普通链表和循环链表的通用场景,更推荐使用方案2。
方案2:封装链表类主动解环
所有节点next保持shared_ptr,封装链表容器类,类内持有头节点的强引用,析构时主动将尾节点的next置空打破循环,即可触发所有节点的正常析构:
struct Elem { string cargo; shared_ptr<Elem> next; Elem(string cargo) { this->cargo = cargo; } ~Elem() { cout << "delete Elem " << cargo << endl; } }; class CyclicList { public: shared_ptr<Elem> head; shared_ptr<Elem> tail; ~CyclicList() { if (tail) tail->next.reset(); // 主动打破循环 } static CyclicList make3() { CyclicList list; list.head = shared_ptr<Elem>(new Elem("A")); auto B = shared_ptr<Elem>(new Elem("B")); auto C = shared_ptr<Elem>(new Elem("C")); list.head->next = B; B->next = C; C->next = list.head; list.tail = C; return list; } }; static void test3() { CyclicList list = CyclicList::make3(); auto head = list.head->next; cout << "elem A should not be deleted yet" << endl; // list离开作用域时析构自动解环,所有节点正常释放 }
带父指针的树结构修复
树的所有权逻辑是父节点持有子节点的所有权,子节点指向父节点属于非所有权的反向引用,因此将parent字段改为weak_ptr即可解决循环引用问题:
struct Node { weak_ptr<Node> parent; // 仅此处改为weak_ptr Node(shared_ptr<Node> parent) { this->parent = parent; if (parent!=nullptr) depth = parent->depth+1; } int depth = 0; vector<shared_ptr<Node>> children; shared_ptr<Node> addChild(shared_ptr<Node> parent) { shared_ptr<Node> child(new Node(parent)); children.push_back(child); return child; } };
使用父指针时调用parent.lock()即可转为可用的shared_ptr,如果父节点已经被销毁,lock()会返回空指针,可自行判断处理。
weak_ptr计数原理解答
你之前的认知偏差是混淆了对象本身和控制块的生命周期:
shared_ptr和weak_ptr共同指向同一个独立的控制块(即你提到的计数辅助对象),控制块中存储强引用计数、弱引用计数、删除器等信息。- 当强引用计数归零时,对象本身会被立即销毁,此时弱引用计数可能还不为零,控制块会继续存在,直到所有
weak_ptr都被释放、弱引用计数也归零后,控制块才会被销毁。 - 不存在「控制块先释放、对象还存在」的可能,控制块的生命周期始终长于对象本身的生命周期。
内容的提问来源于stack exchange,提问作者Saku
相关产品推荐
相关产品推荐

