C++11智能指针——weak_ptr

weak_ptr是为了解决shared_ptr的自引用以及交叉引用而引入的智能指针。顾名思义,weak_ptr是弱指针,因为其不具备指针的一系列操作:operator *,operator->,operator[]等,也不管理具体的原始指针。它仅仅作为一个观察者,协助shared_ptr管理原始指针。它既不使引用计数增减也不拥有原始指针,而且weak_ptr不可以直接使用原始指针进行构造,只能使用shared_ptr或另外一个weak_ptr来构造。虽然weak_ptr不管理原始指针,但是可以使用lock操作来返回一个shared_ptr。weak_ptr实现了拷贝构造函数和重载了赋值操作符,因此weak_ptr可以被用于标准容器库中的元素,例如:在一个树节点中声明子树节点std::vector<boost::weak_ptr<Node> >children。作为观察者,weak_ptr主要的操作有以下几种:  
shared_ptr<T>   lock() const;
long use_count() const;
bool expired() cosnt;//判断指针是否失效void reset();
void swap(weak_ptr<T> &b);

weak_ptr在自引用中的使用
weak_ptr很重要的一个作用是获取this指针的shared_ptr,使对象自己能够缠身管理自己的shared_ptr:对象使用weak_ptr观测this指针,并不影响引用计数,在需要的时候就调用lock函数,返回一个符合要求的shared_ptr供外界使用。这个方法被实现为一个模板类:
class enable_shared_from_this{public: shared_ptr shared_from_this();//工厂函数,产生this的shared_ptr};
使用shared_ptr管理this,必须使被管理的类public继承自enable_shared_from_this。以下为boost程序库完全开发指南第三版(page85 3.63)中的例子:

#include <iostream>
#include <memory>
using namespace std;
class self_shared:public enable_shared_from_this<self_shared>
{
    public: self_shared(int n):x(n){}
    void print() { cout << "self_shared x:" << x << endl; } 
    int x;
};
int main()
{   
    shared_ptr<self_shared> sp = make_shared<self_shared>(335); 
    sp->print();    
    auto p = sp->shared_from_this();    
    p->x = 100; 
    p->print(); 
    getchar();   
    return 0;
}
weak_ptr在交叉引用中的使用   先看一个《C++标准库——第二版》中交叉引用的例子:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <vector>
#include <memory>
using namespace std;

#define OUT_PTR_USE_COUNT(variable) do{\
    cout << #variable << ".use_count() = " << variable.use_count() << endl;\
}while(0);

class Person {
public:
    string name;
    shared_ptr<Person> mother;
    shared_ptr<Person> father;
    vector<shared_ptr<Person>> kids;
    Person(const string& n,
        shared_ptr<Person> m = nullptr,
        shared_ptr<Person> f = nullptr)
        : name(n), mother(m), father(f) {
    }
    ~Person() {
        cout << "delete " << name << endl;
    }
};

shared_ptr<Person> initFamily(const string& name)
{
    shared_ptr<Person> mom(new Person(name + "’s mom"));
    OUT_PTR_USE_COUNT(mom);                                     //cout:1
    shared_ptr<Person> dad(new Person(name + "’s dad"));
    shared_ptr<Person> kid(new Person(name, mom, dad));
    OUT_PTR_USE_COUNT(mom);                                     //cout:2
    mom->kids.push_back(kid);
    dad->kids.push_back(kid);
    OUT_PTR_USE_COUNT(mom);                                     //cout:2
    return kid;
}
int main()
{
    shared_ptr<Person> p = initFamily("nico");
    cout << "- nico is shared " << p.use_count() << " times" << endl;   //cout:3
    return 0;

    //Person was not deleted when process return
}

由于交叉引用,导致在工厂函数initFamily中,mom在生命周期结束时,其引用计数由2变为1,造成自身没有被析构,然后导致child一直被mom和dad所持有,在声明周期结束时也没有被析构。从运行结果来看,所有的交叉引用的person对象都没有被析构!运行结果如下:
这里写图片描述

若在交叉引用的类中使用weak_ptr代替shared_ptr所有的问题都将得到解决。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值