boost::weak_ptr和enable_shared_from_this

shared_ptr在我的实践中使用很广,在接口层面上,我基本都会默认的使用shared_ptr.而weak_ptr则很少使用;即便使用,也是间接的使用,例如使得class A继承自boost::enable_shared_from_this,这样A便具有了一个weak_ptr的成员对象,我便可以通过接口shared_from_this()得到一个boost::shared_ptr<A>的对象.

除此之外,在实践中我几乎没有用到weak_ptr.到目前为止,我见到的对weak_ptr论述最好的是<<Beyond.the.C.plus.plus.Standard.Library.An.Introduction.to.Boost>>.本书给出了使用weak_ptr的三种场景: 打破递归的依赖关系;使用一个共享的资源而不需要共享所有权;避免悬空的指针.

后面两种场景相对比较容易明白,对于第一种则相对模糊.最近几天我相对仔细的研究了一下shared_ptr和weak_ptr的源代码,给出我自己的理解如下.

weak_ptr是依附于shared_ptr的,所以首先要把shared_ptr弄清楚;另外,我认为boost::enable_shared_from_this是解释递归的依赖关系的最好例子,所以使用这个实例解释weak_ptr最好不过了.

shared_ptr的图解

如图所示,3个智能指针对象sp1,sp2,sp3,共享同一个对象object和同一个计数器counter,当3个指针对象sp1,sp2,sp3声明周期结束的时候,counter==0,object会被销毁(当然,这个销毁器本身可以由你定制).

shared_ptr的一个很大的特点是:counter==0,object会被销毁;反之,如果counter总是不为0,那么object会成为永久对象,例如全局对象.

在http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/sp_techniques.html中给出了一个从this获得shared_ptr的实例,答案是使用weak_ptr,问题是为什么是weak_ptr.

让我们把这个问题重新说明一下:

struct X

{

boost::shared_ptr<X>getX()

{

boost::shared_ptr<X>r ;//????如何实现

return r;

}

};

要得到X的智能指针,只是在对象指针是受shared_ptr保护的基础上的,举例如下:

void test_X()

{

{

X x;

boost::shared_ptr<X> px =x.getX();//错误

}

{

X* x = new X();

boost::shared_ptr<X> px = x->getX();//错误

}

{

boost::shared_ptr<X>  x (new X());

boost::shared_ptr<X> px = x->getX();//正确

}

}

我们再回到原来的问题上,如何实现X::getX()函数.要构造X的智能指针,需要知道两个信息,object的指针和object的计数器,显然,指针本身可以通过this获得,问题是如何获得计数器,也即上面图中的counter.很显然,我们必须在X上存储某些信息来得到计数器.

最先想到的也许是使用一个指向counter的指针存储在X上面,这样应该是可以的,但是存在一个问题:暴露了shared_ptr的实现细节,虽然shared_ptr是基于计数器的,但是这不属于用户需要知道的事情.最好的方式是让shared_ptr本身来充当这个角色,这样所有的实现细节就都封装在shared_ptr内部了.

经过这样改装的shared_ptr的图解是:

 
 
 

经过这样包装的object,问题立刻暴露出来:循环引用,造成object对象无法释放,成为”全局对象”.很显然,问题在于object本身参与了引用计数,也就是所有权的分享.我们需要的是不同于shared_ptr的这样的一类共享指针:他们并不参与对象的所有权,只是能够观察到对象的所有权.而这正是weak_ptr的本质所在.

当然了,weak_ptr还有其他的特征:查看对象指针是否过期(这也是比裸指针好的地方).

循环引用的情况很罕见,这可能也是我在实际中很少使用weak_ptr的原因吧.

boost::weak_ptr和enable_shared_from_this相关推荐

  1. boost::weak_ptr相关的测试程序

    boost::weak_ptr相关的测试程序 实现功能 C++实现代码 实现功能 boost::weak_ptr相关的测试程序 C++实现代码 #include <boost/config.hp ...

  2. Boost智能指针——weak_ptr

    循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引用的对象.一个简单的例子如下: #include <string> #include <ios ...

  3. 【Boost】boost库中智能指针——weak_ptr

    循环引用: 引用计数是一种便利的内存管理机制,但它有一个很大的缺点,那就是不能管理循环引用的对象.一个简单的例子如下: #include <string> #include <ios ...

  4. Boost智能指针——shared_ptr

    boost::scoped_ptr虽然简单易用,但它不能共享所有权的特性却大大限制了其使用范围,而boost::shared_ptr可以解决这一局限.顾名思义,boost::shared_ptr是可以 ...

  5. boost之asio异步io使用实例

    // boost_asio_client.cpp : 定义控制台应用程序的入口点. //#include "stdafx.h" #include <boost/asio.hp ...

  6. boost之asio同步io使用实例

    // boost_sync_client.cpp : 定义控制台应用程序的入口点. //#include "stdafx.h"#include <boost/asio.hpp ...

  7. 【Boost】以boost::function和boost:bind取代虚函数

    这是一篇比较情绪化的blog,中心思想是"继承就像一条贼船,上去就下不来了",而借助boost::function和boost::bind,大多数情况下,你都不用上贼船. boos ...

  8. boost::function和boost:bind取代虚函数

    这是一篇比较情绪化的blog,中心思想是"继承就像一条贼船,上去就下不来了",而借助boost::function和boost::bind,大多数情况下,你都不用上贼船. boos ...

  9. Boost高性能网络编程

    Boost高性能网络编程 Boost高性能网络编程    2010-10-25 13:04 一.课程目标 本次课程围绕高性能网络编程这一主题,从众多的Boost类库中挑选出Boost.Asio.Boo ...

最新文章

  1. IO复用之epoll系列
  2. SAP RETAIL Site BP Customer 相同的code ?
  3. emeditor利用书签功能导出匹配结果到新文件
  4. 继承之后的使用注意事项_ArrayStoreException
  5. 如何改变 Python 中线程的执行顺序
  6. android 全局对话框(不依赖具体activity)
  7. 协同遗漏的效果–使用简单的NIO客户端/服务器测量回送延迟
  8. Tomcat集群和Session共享的配置方法
  9. java演练代码 银行取款演练 java
  10. 玩转 SpringBoot 2 快速搭建 | Spring Tool Suite篇
  11. 施工部署主要不包括_施工部署是什么?准备工作是什么?
  12. 【github系列】github创建tag
  13. java中switch条件_关于java:你能在Android的switch-case中使用条件语句吗?
  14. objective-c和java哪个简单_Objective-C和Java的简单对比
  15. (CVPR-2021)具有深度通用线性嵌入的跨视角步态识别
  16. hpgs2wnd.exe
  17. QT5.14.2+VS2019 构建套件(Kit)黄色感叹号问题解决
  18. 【计算机图形学】零 · 计算机图形系统概述
  19. Rimworld Mod制作教程1 认识Mod结构
  20. 脖子为什么越按越疼?

热门文章

  1. Azkaban WebApi 调用
  2. JAVA8后接口的新特性
  3. Java遍历Map的4种方式
  4. mysql图片jsp_mysql jsp 图片
  5. oracle linux6 u盘安装,U盘安装RHEL6
  6. Java中的NIO非阻塞编程
  7. HDU-4027 Can you answer these queries? --线段树
  8. NanUI文档 - 如何实现C#与Javascript的相互通信
  9. 在latex或者mathtype中如何输入花体,如拉式量L
  10. 领域模型(domain model)贫血模型(anaemic domain model)充血模型(rich domain model)