C++11新特性——智能指针之weak_ptr

此课件及源代码来自B站up主:码农论坛,该文章仅作为本人学习笔记使用。

一、shared_ptr存在的问题

shared_ptr内部维护了一个共享的引用计数器,多个shared_ptr可以指向同一个资源。

如果出现了循环引用的情况,引用计数永远无法归0,资源不会被释放。

示例:

#include 
#include 
using  namespace std;

class BB;

class AA
{
public:
      string m_name;

      AA() { cout << m_name << "调用构造函数AA()。\n"; }
      AA(const string & name) : m_name(name) { cout << "调用构造函数AA("<< m_name << ")。\n"; }
      ~AA() { cout << "调用了析构函数~AA(" << m_name << ")。\n"; }

      shared_ptr m_p;
};

class BB
{
public:
      string m_name;

      BB() { cout << m_name << "调用构造函数BB()。\n"; }
      BB(const string& name) : m_name(name) { cout << "调用构造函数BB(" << m_name << ")。\n"; }
      ~BB() { cout << "调用了析构函数~BB(" << m_name << ")。\n"; }

      shared_ptr m_p;
};

int main()
{
      shared_ptr pa = make_shared("a");
      shared_ptr pb = make_shared("b");

      pa-> m_p = pb;
      pb->m_p = pa;
}

二、weak_ptr是什么

weak_ptr 是为了配合shared_ptr而引入的,它指向一个由shared_ptr管理的资源但不影响资源的生命周期。也就是说,将一个weak_ptr绑定到一个shared_ptr不会改变shared_ptr的引用计数。

不论是否有weak_ptr指向,如果最后一个指向资源的shared_ptr被销毁,资源就会被释放。

weak_ptr更像是shared_ptr的助手而不是智能指针。

示例:

#include 
#include 
using  namespace std;

class BB;

class AA
{
public:
      string m_name;

      AA() { cout << m_name << "调用构造函数AA()。\n"; }
      AA(const string & name) : m_name(name) { cout << "调用构造函数AA("<< m_name << ")。\n"; }
      ~AA() { cout << "调用了析构函数~AA(" << m_name << ")。\n"; }

      weak_ptr m_p;
};

class BB
{
public:

      string m_name;

      BB() { cout << m_name << "调用构造函数BB()。\n"; }
      BB(const string& name) : m_name(name) { cout << "调用构造函数BB(" << m_name << ")。\n"; }
      ~BB() { cout << "调用了析构函数~BB(" << m_name << ")。\n"; }

      weak_ptr m_p;
};

int main()
{
      shared_ptr pa = make_shared("a");
      shared_ptr pb = make_shared("b");

      cout << "pa.use_count()=" << pa.use_count() << endl;
      cout << "pb.use_count()=" << pb.use_count() << endl;

      pa->m_p = pb;
      pb->m_p = pa;

      cout << "pa.use_count()=" << pa.use_count() << endl;
      cout << "pb.use_count()=" << pb.use_count() << endl;
}

三、如何使用weak_ptr

weak_ptr没有重载 ->和 *操作符,不能直接访问资源。

有以下成员函数:

1)operator=();  // 把shared_ptr或weak_ptr赋值给weak_ptr。

2)expired();     // 判断它指资源是否已过期(已经被销毁)。

3)lock();        // 返回shared_ptr,如果资源已过期,返回空的shared_ptr。

4)reset();       // 将当前weak_ptr指针置为空。

5)swap();       // 交换。

weak_ptr不控制对象的生命周期,但是,它知道对象是否还活着。

用lock()函数把它可以提升为shared_ptr,如果对象还活着,返回有效的shared_ptr,如果对象已经死了,提升会失败,返回一个空的shared_ptr。

提升的行为(lock())是线程安全的。

示例:

#include 
#include 
using  namespace std;

class BB;

class AA
{
public:
      string m_name;

      AA() { cout << m_name << "调用构造函数AA()。\n"; }
      AA(const string& name) : m_name(name) { cout << "调用构造函数AA(" << m_name << ")。\n"; }
      ~AA() { cout << "调用了析构函数~AA(" << m_name << ")。\n"; }

      weak_ptr m_p;
};

class BB
{
public:
      string m_name;

      BB() { cout << m_name << "调用构造函数BB()。\n"; }
      BB(const string& name) : m_name(name) { cout << "调用构造函数BB(" << m_name << ")。\n"; }
      ~BB() { cout << "调用了析构函数~BB(" << m_name << ")。\n"; }

      weak_ptr m_p;
};

int main()
{
      shared_ptr pa = make_shared("a");
      {
            shared_ptr pb = make_shared("b");

            pa->m_p = pb;
            pb->m_p = pa;

            shared_ptr pp = pa->m_p.lock();            // 把weak_ptr提升为shared_ptr。
            if (pp == nullptr)
                 cout << "语句块内部:pa->m_p已过期。\n";
            else
                 cout << "语句块内部:pp->m_name=" << pp->m_name << endl;
      }

      shared_ptr pp = pa->m_p.lock();            // 把weak_ptr提升为shared_ptr。
      if (pp == nullptr)
            cout << "语句块外部:pa->m_p已过期。\n";
      else
            cout << "语句块外部:pp->m_name=" << pp->m_name << endl;
}

你可能感兴趣的:(C++,c++,开发语言)