zoukankan      html  css  js  c++  java
  • weak_ptr 使用

    转自 https://blog.csdn.net/ajioy/article/details/7377099

     weak_ptr是为配合shared_ptr而引入的一种智能指针,它更像是shared_ptr的一个助手,而不是智能指针,因为它不具有普通指针的行为,没有重载operator*和operator->,它的最大作用在于协助shared_ptr,像旁观者那样观测资源的使用情况。

    类摘要:

    1. template<class T> class weak_ptr{
    2. public:
    3. weak_ptr();
    4. template<class Y> weak_ptr(shared_ptr<Y> const & r);
    5. weak_ptr(weak_ptr const & r);
    6. ~weak_ptr();
    7. weak_ptr & operator=(weak_ptr const &r);
    8. long use_count() const;
    9. bool expired() const;
    10. shared_ptr<T> lock() const;
    11. void reset();
    12. void swap(weak_ptr<T> &b);
    13. };


    weak_ptr是一个“弱”指针,但它能够完成一些特殊的工作,足以证明它的存在价值。

    weak_ptr被设计为与shared_ptr共同工作,可以从一个shared_ptr或者另一个weak_ptr对象构造,获得资源的观测权。但weak_ptr没有共享资源,它的构造不会引起指针引用计数的增加。同样,在weak_ptr析构时也不会导致引用计数的减少,它只是一个静静地观察者。

    使用weak_ptr的成员函数use_count()可以观测资源的引用计数,另一个成员函数expired()的功能等价于use_count() == 0,但更快,表示观测的资源(也就是shared_ptr管理的资源)已经不复存在了。

    weak_ptr 没有重载operator*和->,这是特意的,因为它不共享指针,不能操作资源,这是它弱的原因。但它可以使用一个非常重要的成员函数lock()从被观测的shared_ptr获得一个可用的shared_ptr对象,从而操作资源。当expired() == true的时候,lock()函数将返回一个存储空指针的shared_ptr。

    使用示例:

    1. int main(){
    2. shared_ptr<int> sp(new int(10));
    3. assert(sp.use_count() == 1);
    4. //create a weak_ptr from shared_ptr
    5. weak_ptr<int> wp(sp);
    6. //not increase the use count
    7. assert(sp.use_count() == 1);
    8. //judge wp is invalid
    9. //expired() is equivalent with use_count() == 0
    10. if(!wp.expired()){
    11. shared_ptr<int> sp2 = wp.lock();//get a shared_ptr
    12. *sp2 = 100;
    13. assert(wp.use_count() == 2);
    14. cout << *sp2 << endl;
    15. }//out of scope,sp2 destruct automatically,use_count()--;
    16. assert(wp.use_count() == 1);
    17. sp.reset();//shared_ptr is invalid
    18. assert(wp.expired());
    19. assert(!wp.lock());
    20. }


    获得this的shared_ptr

    weak_ptr的一个重要用途是获得this指针的shared_ptr,使对象自己能够生产shared_ptr管理自己:对象使用weak_ptr观测this指,这并不影响引用计数,在需要的时候就调用lock()函数,返回一个符合要求的shared_ptr使外界使用。

    这个解决方案被实现为一个惯用法,在头文件<booost/enable_shared_from_this.hpp>定义了一个助手类enable_shared_from_this<T>,其声明如下:

    1. template<class T>
    2. class enable_shared_from_this
    3. {
    4. public:
    5. shared_ptr<T> shared_from_this();
    6. }


    使用的时候只需要让想被shared_ptr管理的类从它继承即可,成员函数shared_from_this()会返回this的shared_ptr

    使用示例:

    1. #include <iostream>
    2. #include <boost/smart_ptr.hpp>
    3. #include <boost/enable_shared_from_this.hpp>
    4. #include <boost/make_shared.hpp>
    5. using namespace boost;
    6. using namespace std;
    7. class self_shared:
    8. public enable_shared_from_this<self_shared>{
    9. public:
    10. self_shared(int n):x(n){}
    11. int x;
    12. void print(){
    13. cout << "self_shared:" << x << endl;
    14. }
    15. };
    16. int main(){
    17. shared_ptr<self_shared> sp =
    18. make_shared<self_shared>(315);
    19. sp->print();
    20. shared_ptr<self_shared> p = sp->shared_from_this();
    21. p->x = 100;
    22. p->print();
    23. }


    运行结果:

    self_shared:315
    self_shared:100

    需要注意的是千万不能从一个普通对象(非shared_ptr)使用shared_from_this ()获取shared_ptr,如

    self_shared ss;

    shaerd_ptr<self_shared> p = ss.shared_from_this();//error

    这样虽然语法上能通过,编译也无问题,但在运行时会导致shared_ptr析构时企图删除一个栈上分配的对象,发生未定义行为。

    关于intrusive_ptr

    intrusive_ptr是一个侵入式的引用计数型指针,它可以用于以下情形:

    对内存占用的要求非常严格,要求必须与原始指针一样;

    现存代码已经有了引用计数机制管理的对象。

    boost库不推荐intrusive_ptr,因为shared_ptr已经非常强大且灵活,工作得足够好,可以满足绝大部分(99.99%)的需要。

    如果有兴趣,可以自行翻阅boost文档。

  • 相关阅读:
    Flutter-路由
    写一个底部Tabs导航动态组件
    实例:Flutter布局01
    HTTP报文
    HTML文本的各种属性
    HTML必要简介和基础
    MySQL8.0.23安装超详细傻瓜式
    从一个HTTP请求来研究网络分层原理
    MySQL的增删改查
    MySQL常用数据类型有哪些?
  • 原文地址:https://www.cnblogs.com/ymd12103410/p/11136790.html
Copyright © 2011-2022 走看看