循环引用问题
当两个对象相互持有 shared_ptr 时,引用计数永远不会归零,导致内存泄漏。
class B; // 前向声明
class A {
public:
std::shared_ptr<B> b_ptr;
~A() { std::cout << "A destroyed" << std::endl; }
};
class B {
public:
std::shared_ptr<A> a_ptr;
~B() { std::cout << "B destroyed" << std::endl; }
};
int main() {
auto a = std::make_shared<A>();
auto b = std::make_shared<B>();
a->b_ptr = b;
b->a_ptr = a;
// 离开作用域时,a 和 b 的引用计数均为 1,不会析构!
return 0;
}使用 weak_ptr 打破循环
将其中一个指针改为 weak_ptr,不增加引用计数。
class A {
public:
std::shared_ptr<B> b_ptr;
};
class B {
public:
std::weak_ptr<A> a_ptr; // 使用 weak_ptr
};
// 使用时需 lock() 提升为 shared_ptr
if (auto sp = a_ptr.lock()) {
// 安全使用 sp
}最佳实践
- 观察者模式:被观察者持有观察者的
weak_ptr。 - 缓存:缓存对象使用
weak_ptr,外部可随时释放。
weak_ptr 是解决悬垂指针和循环引用的利器。
