首页 > 其他 > 详细

shared_ptr / weak_ptr 代码片段

时间:2015-11-21 11:42:21      阅读:445      评论:0      收藏:0      [点我收藏+]

参考<<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 <boost\make_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

 

  

shared_ptr / weak_ptr 代码片段

原文:http://www.cnblogs.com/roger9567/p/4982933.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!