C++11智能指针之weak_ptr

来源:互联网 发布:excel数据递增 编辑:程序博客网 时间:2024/06/07 03:03


   weak_ptr是一种弱智能指针,它具有类似shared_ptr的行为,但是却不会影响的它所指向的资源的引用计数。Weak_ptr不能被解引用,也不能被测试是否为null

weak_ptr之所以具备这些特点,是因为weak_ptr不是一个独立的指针,而是shared_ptr的一个附加物。Weak_ptr是通过shared_ptr创建出来的,正像如下代码:

   auto spw =std::make_shared<Investment>();

std::weak_ptr<Investment>wpw(spw);

如果此时,将spw赋值为nullspw所管理的资源会被析构,那么wpw也就成为了悬空指针,也称为“过期”(expired),可以通过expired()判断weak_ptr是否过期。

   spw =nullptr;

if (!wpw.expired()) {}

 

在使用weak_ptr时,我们通常会考虑先用expired()判断其是否过期,如果没有过期,就通过它来访问所管理的资源,但是我们在一开头的时候说过,weak_ptr不能被解引用,所以,自然我们也不可能用它来访问它所指向的资源,即便weak_ptr可以被解引用,这么做也是不安全的,因为判断是否过期和解引用是两个独立的动作,在多线程环境下,会出现线程竞争,所以这不是一种线程安全的做法。

正确的做法是,当我们想要访问weak_ptr所指向的资源时,应当将weak_ptr转为一个shared_ptr,通过shared_ptr来访问资源。这里有两种方法来做这件事:

1通过weak_ptrlock()调用

std::shared_ptr<Investment>spw1 = wpw.lock();//如果wpw过期,则返回null

2weak_ptr作为shared_ptr构造函数的参数

std::shared_ptr<Investment>spw2(wpw);

       那么,既然weak_ptr无法被解引用,那它到底有什么用处呢?

       weak_ptr的用处主要体现在两方面:

  1. 需要获知所管理的资源是否过期

设想在观察者模式中,最重要的两个角色是主体和观察者,主体中拥有某种资源,并且维护了一个观察者列表,当主体拥有的某种资源的状态发生变化时,主体就会通知观察者列表中的观察者,观察者得到这个通知后,会针对这个变化进行相应的操作。

在观察者模式中,主体无法主宰观察者列表中的观察者的生命周期,它只需要知道,在列表中的这些观察者是否“健在”就可以了,所以,我们可以用一个元素类型为weak_ptr的列表来存放主体所拥有的观察者了。

        2. 解决shared_ptr的循环引用问题

shared_ptr的循环引用是指两个对象中都有一个shared_ptr指向另一个对象的情况,如图所示:

 

       如果A要析构的话,就会首先尝试去销毁它所管理的资源,即销毁B,但是B中也有一个shared_ptr指向了AB要析构,也会去尝试首先销毁它所拥有的资源,即销毁A,这样的话,就会出现无限循环,两个对象都无法被销毁,从而造成内存泄漏。

       解决循环引用的办法就是,使用weak_ptr,如图所示,在B中使用weak_ptr指向A,这时候就不会出现循环引用的问题了

原创粉丝点击