C++智能指针——weak_ptr详解

前言
  weak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少.  同时weak_ptr 没有重载*和->但可以使用 lock 获得一个可用的 shared_ptr 对象。C++智能指针——share_ptr详解 使用陷阱中提到循环引用导致对象无法被析构的问题,通过weak_ptr可以解决

#ifndef testA_H
#define testA_H

#include <memory>
using namespace std;

class testB;
class testA {
    public:
    testA();
    ~testA();
    void testFunA(const shared_ptr<testB> &sptr);

    private:
    shared_ptr<testB> m_sptrB;
};
#endif

=====================================================================
#include "testA.h"
#include <iostream>
using namespace std;

testA::testA(){}

void testA::testFunA(const shared_ptr<testB> &sptr) {
    cout<<"testFunA"<<endl;
    m_sptrB = sptr;
}
testA::~testA(){
    cout<<"~testA destructor"<<endl;
}

=====================================================================
#ifndef testB_H
#define testB_H

#include <memory>

using namespace std;
class testA;
class testB {
    public:
    testB();
    ~testB();

    void testFunB(const shared_ptr<testA> &sptr);

    private:
    weak_ptr<testA>m_sptrA; //使用weak_ptr替换shared_ptr
};
#endif

=====================================================================
#include "testB.h"
#include <iostream>
using namespace std;

testB::testB(){}

void testB::testFunB(const shared_ptr<testA> &sptr) {
    cout<<"testFunB"<<endl;
    m_sptrA = sptr;
}

testB::~testB(){
    cout<<"~testB destructor"<<endl;
}

=====================================================================

int main(int argc, char const *argv[])
{
    testA *ta = new testA();
    testB *tb = new testB();
    shared_ptr<testA> sptra(ta);
    shared_ptr<testB> sptrb(tb);

    sptra->testFunA(sptrb);
    sptrb->testFunB(sptra);
}

输出结果:

testFunA
testFunA m_sptrB count = 2
testFunB
testFunB m_sptrA count = 1  //在testB类中用weak_ptr不会修改引用计数
~testA destructor
~testB destructor

weak_ptr常用函数介绍:

  • use_count函数,表示当前引用计数
  • reset函数,表示删除当前被管理的对象。
  • expired函数,表示判断被管理的对象是否被删除,相当于use_count()==0,如果被删除则返回true,否则返回false。
    shared_ptr<int> sptr(new int(2));
    weak_ptr<int> wptr(sptr);
    cout<<"wptr count = "<<wptr.use_count()<<endl;  //输出结果:1
    cout<<"wptr expired = "<<wptr.expired()<<endl;  //输出结果:0

    wptr.reset();
    cout<<"wptr count = "<<wptr.use_count()<<endl;  //输出结果:0
    cout<<"wptr expired = "<<wptr.expired()<<endl;  //输出结果:1

lock函数,该函数从资料上解释如下:

Lock and restore weak_ptr

Returns a shared_ptr with the information preserved by the weak_ptr object if it is not expired.

If the weak_ptr object has expired (including if it is empty), the function returns an empty shared_ptr (as if default-constructed).

Because shared_ptr objects count as an owner, this function locks the owned pointer, preventing it from being released (for at least as long as the returned object does not releases it).

This operation is executed atomically.

上述描述理解如下:

如果waak_ptr管理的对象不为空,则返回一个shared_ptr,否则返回一个空的 shared_ptr;此函数锁定所拥有的指针,防止其被释放。

    shared_ptr<int> sp1,sp2;
    weak_ptr<int> wp;
    sp1 = make_shared<int> (20);    // sp1
    wp = sp1;                       // sp1, wp

    cout<<"wp count = "<<wp.use_count()<<endl; count = 1

    sp2 = wp.lock();                // lock返回的是一个shared_ptr,赋值给sp2时引用计数加1

    cout<<"sp2 count = "<<sp2.use_count()<<endl;  count = 2
    cout<<"sp1 count = "<<sp1.use_count()<<endl;  count = 2

    sp1.reset();                    // 重置当前管理的指针,引用计数归零

    cout<<"sp1 count = "<<sp1.use_count()<<endl; count = 0
    cout<<"wp count = "<<wp.use_count()<<endl; count = 1,之前调用了lock防止被释放
    
    sp1 = wp.lock(); //wp.lock放回是shared_ptr,赋值之后引用计数加1 

    cout<<"sp1 count = "<<sp1.use_count()<<endl; count = 2
    cout<<"sp2 count = "<<sp2.use_count()<<endl; count = 2        
  • swap函数,表示交换weak_ptr管理对象和swap参数里边的内容。
    std::shared_ptr<int> sp1 (new int(10));
    std::shared_ptr<int> sp2 (new int(20));

    std::weak_ptr<int> wp1(sp1);
    std::weak_ptr<int> wp2(sp2);

    cout<<"wp1 = "<<*wp1.lock()<<endl;  // 10
    cout<<"wp2 = "<<*wp2.lock()<<endl;  // 20

    wp1.swap(wp2);

    cout<<"wp1 = "<<*wp1.lock()<<endl;  // 20
    cout<<"wp2 = "<<*wp2.lock()<<endl;  // 10

参考:http://www.cplusplus.com/reference/memory/weak_ptr/

发布了88 篇原创文章 · 获赞 17 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/yj_android_develop/article/details/88917290