C++11智能指针——weak_ptr

来源:互联网 发布:火线精英手游刷枪软件 编辑:程序博客网 时间:2024/06/06 15:51
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所有的问题都将得到解决。

0 0
原创粉丝点击