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

      

  • 相关阅读:
    redis 高级
    redis连接
    redis脚本
    Redis事务
    redis发布订阅
    加一
    C语言从代码中加载动态链接库
    GCC编译器
    Vim编辑器基础
    Linux用户的创建与授权及修改密码
  • 原文地址:https://www.cnblogs.com/roger9567/p/4982933.html
Copyright © 2011-2022 走看看