zoukankan      html  css  js  c++  java
  • shared_ptr / weak_ptr 代码片段

    参考<<Boost程序库完全开放指南>>

     shared_ptr  类摘要(只列出了常用的部分)和相关说明

     1 template <class T> class shared_ptr {
     2 public:
     3     typedef T element_type;
     4     shared_ptr();
     5     template<class Y> explicit shared_ptr(Y * p);
     6     template<class Y, class D> shared_ptr(Y * p); // 定制删除器 d取代简单的delete. 要求能用d()函数方式调用, d可以是函数对象或者函数指针.
     7     ~shared_ptr();
     8 
     9     shared_ptr(shared_ptr const & r);
    10     template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);
    11 
    12     //比较运算符的比较是基于内部保存的指针.return  a.get() == b.get();
    13     shared_ptr & operator = (shared_ptr const & r);
    14     template<class Y> shared_ptr & operator = (shared_ptr<Y> const & r);
    15     template<class Y> shared_ptr & operator = (std::auto_ptr<Y> & r);
    16 
    17     void reset(); // 将引用计数减一,停止当前指针对原始指针的共享.
    18     template<class Y> void reset(Y * p); // 引用计数减一, 同时转而共享另一个指针.
    19     template<class Y, class D> void reset(Y * p, D d);
    20 
    21     T & operator * () const;
    22     T * operator -> () const;
    23     T * get() const;   // 获取原始指针
    24 
    25     bool unique() const;//高效判断
    26     long use_count() const; // 效率低, 建议只在调试时用.
    27 
    28     operator unspecified_bool_type() const;  // 提供隐式类型转换, 比如放在条件语句中作为bool值
    29     void swap(shared_ptr & b);//交换内部指针
    30 };
    View Code

    1.  shared_ptr r 特点

      - 提供 * ->操作符模仿原始指针行为, 提供隐式bool 类型转换以判断指针的有效性.

      - 没有提供指针算术运算操作,除 < 运算符外. 所以可以用于标准容器.

      - 可以被安全共享, 提供基本的线程安全的保证(一个 shared_ptr 可以被多个线程安全读取).

      - 类型转换不能用诸如: static_cast<T*>(p.get())的形式(导致转换后指针无法再被 shared_ptr 自动管理),  shared_ptr 提供类似的转型函数:  static-pointer_cast<T>() ,  const_pointer_cast<T>()  ,  dynamic_pointer_cast<T>() .

    1 shared_ptr<std::exception> sp1 (new bad_exception("error"));
    2 shared_ptr<bad_exception> sp2 = dynamic_pointer_cast<bad_exception>(sp1);
    3 shared_ptr<std::exception> sp3 = static_pointer_cast<std::exception>(sp2);
    4 assert(sp3 == sp1);

      - 支持 << 操作符, 直接打印内部指针的值, 方便调试.

      - 几乎可以100%在任何new 出现的地方接受new的动态分配结果, 然后被任意使用,完全消灭delete的使用的和内存泄露.

    2.  shared_ptr  的使用技巧

      - 使用工厂函数 make_shared() 来包装new表达式

        -  shared_ptr  消除了显式delete调用, 但是 shared_ptr 构造时需要new, 导致了代码中某种不对称性.

    1 #include <boostmake_shared.hpp>
    2 template<class T, class ...Args>
    3 shared_ptr<T> make_shared(Args && ... args);

        - smart_ptr 也提供了一个 allocate_shared() 工厂函数, 比make_shared()多一个定制的内存分配器参数.

      - 应用于标准容器

        - 将容器作为 shared_ptr的管理对象:   shared_ptr<list<T> > 

        - 将 shared_ptr作为容器的元素:  vector<shared_ptr<T> >  

      - 应用于桥接模式(pimpl或者 handle/body)

        - 将类的具体实现对用户隐藏,达到最小耦合, 可以不使用虚函数实现多态.

     1 class sample {
     2 private:
     3     class impl; 
     4     shared_ptr<impl> p;
     5 public:
     6     sample();
     7     void print();  //提供给外界的接口
     8 };
     9 class sample::impl {
    10 public:
    11     void print() {
    12         cout << "impl print" << endl;
    13     }
    14 };
    15 sample::sample():p(new impl){}
    16 void sample::print() {
    17     p->print(); //调用内部类的impl 实现print.
    18 }
    19 sample s;
    20 s.print();  //实现桥接模式
    View Code

      - 应用于工厂模式(前面的 make_shared() 函数也算)

     1 class abstract {
     2 public:
     3     virtual void f() = 0;
     4     virtual void g() = 0;
     5 protected:
     6     virtual ~abstract(){}  //定义为保护的,只允许自己和子类对象调用.其他任何对象无权调用delete删除.
     7 };
     8 class impl :public abstract{
     9 public:
    10     virtual void f() {
    11         cout << "class impl f" << endl;
    12     }
    13     virtual void g() {
    14         cout << "class impl g" << endl;
    15     }
    16 };
    17 shared_ptr<abstract> create() {
    18     return shared_ptr<abstract>(new impl);
    19 }
    20 int main(){
    21     shared_ptr<abstract> p = create();
    22     p->f();
    23     p->g();
    24     return 0;
    25 }
    26 /* 结果:
    27 class impl f
    28 class impl g
    29 */
    View Code

       - 定制删除器

        - 可以用来自动释放数据库连接, 关闭文件资源等.

     1 class socket_t{};
     2 socket_t * open_socket() {
     3     cout << "open socket" << endl;
     4     return new socket_t;
     5 }
     6 void close_socket(socket_t * s) {
     7     cout << "close socket" << endl;
     8 }
     9 int main(){
    10     socket_t * s = open_socket();
    11     shared_ptr<socket_t> p(s, close_socket);  // 等价: shared_ptr<socket_t> p(s,&close_socket);
    12     return 0;
    13 }//离开作用域时, p为调用定制的删除器 close_socket()
    View Code

         - 对C语言文件操作管理就很简单了:  shared_ptr<FILE> fp(fopen("./1.txt", "r"), fclose()); 

       -  shared_ptr<void> 

        - 优点: 能存储 void * 的指针, 而 void*  可以指向任意类型, 从而变成泛型的指针容器.

        - 缺点: 丧失了原来的类型信息, 为了需要的时候正确使用, 需要用 static_pointer_cast<T> 转换. 转换会使代码不够安全, 建议不这样用.

     1 /*算是删除器的高级用法了吧*/
     2 void any_func(void * p) {
     3     cout << "some operate" << endl;
     4 }
     5 int main(){
     6     shared_ptr<void> p((void*)0, any_func);  //容纳空指针,定制删除器, 实现退出作用域时调用任意函数.
     7     return 0;//退出作用域时执行any_fuc()
     8 }
     9 /*结果
    10 some operate
    11 */
    View Code

      - 其他: 包装成员函数, 延时释放

        - 以后有空再研究

    weak_ptr类摘要

     1 template<class T> class weak_ptr {
     2 public:
     3     template<class Y> weak_ptr(shared_ptr<Y> const & r);
     4     weak_ptr(weak_ptr const & r);
     5     ~weak_ptr();
     6 
     7     weak_ptr & operator = (weak_ptr const & r);
     8 
     9     long use_count() const;//获取观测资源的引用计数
    10     bool expired() const;  //相当于use_count() == 0 , 但是更快
    11     shared_ptr<T> lock() const; // 从被观测的share_ptr获取一个可用的shared_ptr对象, 从而操作资源
    12 
    13     void reset();
    14     void swap(weak_ptr<T> & b);
    15 };
    View Code

    1. weak_ptr  的特点

      - 被设计为与 shared_ptr 共同工作, 可以从一个 shared_ptr  或者另一个 weak_ptr  对象构造获取资源的观测权.

      - 不共享(引用)资源, 不能直接操作资源, 构造/析构不会改变观测资源的引用计数.

      - 没有重载 * 和 -> , 不能像操作指针一样操作它.

    2.weak_ptr 用法

      - 基本用法

     1 int main(){
     2     shared_ptr<int> sp(new int(10));
     3     cout << sp.use_count() << endl;
     4     weak_ptr<int> wp(sp);
     5     cout << wp.use_count() << endl;
     6     if (!wp.expired()) {
     7         shared_ptr<int> sp2 = wp.lock();
     8         *sp2 = 100;
     9         cout << wp.use_count() << endl;
    10     }
    11     cout << wp.use_count() << endl;
    12     sp.reset();
    13     cout << wp.expired() << endl;
    14     cout << !wp.lock() << endl;
    15     return 0;
    16 }
    17 /*结果
    18 1
    19 1
    20 2
    21 1
    22 1
    23 1
    24 */
    View Code

      - 获得this的 shared_ptr 

        -  weak_ptr 获取this指针的 shared_ptr , 使对象能获取shared_ptr实现自我管理. (使用lock() )

        - 已经被通用实现, 在 <boost/enable_shared_from_this.hpp> 内的助手类:  enable_shared_from_this<T> .

     1 class self_shared :public enable_shared_from_this<self_shared> {
     2 public:
     3     int x;
     4     self_shared(int n) :x(n) {}
     5     void print() {
     6         cout << "self_shared:" << x << endl;
     7     }
     8 };
     9 int main(){
    10     shared_ptr<self_shared> sp = make_shared<self_shared>(314);
    11     sp->print();
    12     shared_ptr<self_shared> p = sp->shared_from_this();
    13     p->x = 100;
    14     p->print();
    15     return 0;
    16 }
    17 /*结果
    18 self_shared:314
    19 self_shared:100
    20 */
    View Code

         - 注意不能从一个普通对象(非shared_ptr)使用 shared_from_this()  来获取shared_ptr.

    1 //语法正确, 但是会在shared_ptr析构是企图删除一个栈上分配的对象, 发生未定义行为
    2 self_shared ss;
    3 shared_ptr<self_shared> p = ss.shared_from_this();
    View Code

      

  • 相关阅读:
    【转】win8.1下安装ubuntu
    Codeforces 1025G Company Acquisitions (概率期望)
    Codeforces 997D Cycles in Product (点分治、DP计数)
    Codeforces 997E Good Subsegments (线段树)
    Codeforces 1188E Problem from Red Panda (计数)
    Codeforces 1284E New Year and Castle Building (计算几何)
    Codeforces 1322D Reality Show (DP)
    AtCoder AGC043C Giant Graph (图论、SG函数、FWT)
    Codeforces 1305F Kuroni and the Punishment (随机化)
    AtCoder AGC022E Median Replace (字符串、自动机、贪心、计数)
  • 原文地址:https://www.cnblogs.com/roger9567/p/4982933.html
Copyright © 2011-2022 走看看