4 - weak_ptr

本文将对弱引用智能指针weak_ptr做一些详细的介绍。

介绍

weak_ptrshared_ptr有关,weak_ptr可包含由shared_ptr管理的资源的引用,但不会增加shared_ptruse_count。它在被销毁时不会销毁它指向的资源,可以用于判断资源是否已经被关联的shared_ptr释放。

如果要访问 weak_ptr所管理的对象,我们需要将其转换成shared_ptr

使用

解决shared_ptr的循环引用问题

weak_ptr的出现就是为了弥补shared_ptr出现的一点问题——循环引用

查看下方代码:

class A
{
public:
    std::shared_ptr<B> sharedB;
};

class B
{
public:
    std::shared_ptr<A> sharedA;
}

int main()
{
    std::shared_ptr<A> sA = std::make_shared<A>();
    std::shared_ptr<B> sB = std::make_shared<B>();
    
    sA->sharedB = sB;
    sB->sharedA = sA;
}

这段代码中,sA的sharedB指向初始化好的B对象,sB的sharedA指向初始化好的A对象,当代码执行完,sA和sB被销毁时,发现两对象里的shared_ptr循环引用,无法销毁,这样就导致了内存泄漏问题。

解决问题的方法就是 在两类中任选其一,将shared_ptr改为weak_ptr

class A
{
public:
    std::weak_ptr<B> weakB;
};

这样子就不会发生循环引用,两对象可以被正确销毁。

lock()

使用weak_ptr实例的lock()方法,该方法返回一个shared_ptr。如果同时释放了与weak_ptr相关联的shared_ptr,会返回nullptr

std::shared_ptr<int> shared = weakSimple.lock();

创建一个新的shared_ptr实例

weak_ptr作为shared_ptr构造函数的参数。如果释放了与weak_ptr关联的shared_ptr,则抛出std::bad_weak_ptr异常。

总结

weak_ptr 使用较少,就是为了处理 shared_ptr 循环引用问题而设计的。

参考资料

  • 飘零的落花 - 现代C++详解
  • C++20高级编程