C++ 11新特性之week_ptr

概述

        在C++11 标准中,智能指针的引入极大地提升了内存管理的安全性和便利性。除了已经广为人知的shared_ptr和unique_ptr之外,还有一个重要但相对较少被单独提及的智能指针类型——std::weak_ptr。std::weak_ptr是C++ 11引入的一种弱引用智能指针,它不拥有所指向对象的所有权,而是对shared_ptr持有的对象提供一种非拥有但可观察的访问方式。weak_ptr主要用于打破共享所有权循环引用的问题,防止出现内存泄漏。

工作原理

        1、不增加引用计数。

        当创建一个weak_ptr时,它不会增加其所指向的对象的引用计数。这意味着,即使有多个weak_ptr指向同一对象,只要没有对应的shared_ptr存在,该对象仍会在所有shared_ptr释放后被正确销毁。

        2、检查有效性。

        通过调用weak_ptr的lock()成员函数,可以获取一个指向同一对象的shared_ptr。如果此时对象已被删除,则返回的shared_ptr为空。因此,在使用weak_ptr之前通常需要先调用lock()来检查对象是否仍然有效。

        3、不阻止对象析构。

        由于weak_ptr仅提供了对目标对象的弱引用,所以在没有活跃的shared_ptr指向该对象时,对象会被正常回收。

使用案例

        单纯使用shared_ptr有时会产生问题,考虑下面的示例代码。

#include 
using namespace std;

class A;
class B;

typedef shared_ptr A_Share;
typedef shared_ptr B_Share;

class A
{
public:
    B_Share m_b;
};

class B
{
public:
    A_Share m_a;
};

int main()
{
    A_Share a(new A());
    B_Share b(new B());
    a->m_b = b;
    b->m_a = a;
    return 0;
}

        在上面的示例代码中,a和b相互进行引用。在a和b离开作用域时,a和b的引用计数都是1,内存没有正常释放。解决方法是:将A和B中的任意一个类声明的变量改为week_ptr类型。比如:修改类B后的参考代码如下。

class B
{
public:
    weak_ptr m_a;
};

        修改后,b.m_a = a不会增加A对象的引用计数。因此,a离开作用域时,引用计数为0。B对象的引用计数为2,在a和b离开作用域时,引用计数各减1后也为0,从而被正常释放。

应用场景

        1、打破循环引用。

        在两个或多个具有相互引用关系的对象之间使用shared_ptr时,如果没有弱引用的存在,可能会形成循环引用,导致即使外部不再有任何其他引用,这些对象也无法被垃圾回收。在这种情况下,可以通过将一部分引用改为weak_ptr来解决此问题。

        2、缓存与观察者模式。

        在设计缓存系统或者观察者模式时,某个对象可能需要知道另一个对象的状态变化,但并不希望影响该对象的生命周期。这时,可以使用weak_ptr来跟踪对象,而不增加其引用计数。

总结

        std::weak_ptr作为C++ 11的新特性之一,为了解决循环引用和实现特定设计模式提供了关键工具。理解和熟练运用weak_ptr,有助于编写更加安全且资源高效的C++程序。同时,应当注意在恰当的场景下结合shared_ptr一起使用,以达到最佳效果。

你可能感兴趣的:(C++,11新特性,c++,C++,11,weak_ptr)