2016-11-02: boost::enable_shared_from_this
使用场景
当类对象被shared_ptr管理时,需要在类自己定义的函数中把当前对象作为参数传递给其他函数时,必须传递一个shared_ptr,否则就不能保持shared_ptr管理这个类对象的语义。因为有一个raw pointer指向这个类对象,而shared_ptr对类对象的这个引用没有计数,很可能shared_ptr已经把类对象资源释放了,而那个调用函数还在使用类对象--显然,这肯定会产生错误。
使用方法
在上述场景中,我们需要在类内部获得自己的shared_ptr。我们可以让自己定义的类继承boost::enable_shared_from_this。因为,boost中的enable_shared_from_this类提供了一个shared_frome_this()成员函数可以让子类内部获得自身的shared_ptr对象,满足类实现过程中需要传递自身shared_ptr的使用需求。
注意事项
虽然enable_shared_from_this是基类,但它却是在shared_ptr里面初始化enable_shared_from_this的成员weak_ptr。因此不能在子类的构造方法里面调用shared_from_this(),因为这个时候weak_ptr还是空值。
为什么在类的内部不直接使用this指针,因为我们程序中用shared_ptr来管理指针,如果我们在类的内部传递的过程中用原始指针,这样类内部的引用shared_ptr不会察觉到,因为有可能我们传进去的时候已经被shared_ptr释放掉了。
实现原理
限制条件
在类对象本身当中不能存储类对象本身的 shared_ptr,否则类对象 shared_ptr 的引用计数永远也不会为0了,从而资源永远不会释放,除非程序结束。
类对象肯定是外部函数通过某种机制分配的,而且一经分配立即交给 shared_ptr 管理(再次强调一遍:给 shared_ptr 管理的资源必须在分配时交给 shared_ptr),而且以后凡是需要共享使用类对象的地方必须使用这个 shared_ptr 当作右值来构造产生或者拷贝产生另一个 shared_ptr 从而达到共享使用的目的。(即you must never create more than one shared_ptr from the same raw pointer)
可能方案
有了以上两点的限制,要实现我们的目标(即在类对象内部使用类对象的 shared_ptr)有以下两种方案:
1、类对象的外部 shared_ptr 作为函数参数传给类的需要引用类对象自身的函数——显然,这种方法很丑陋,而且并不是所有的情况都可行(如在外部 shared_ptr 不可见的作用域中就不行);
2、类对象自身存储某种信息,在需要自身 shared_ptr 时来产生一个临时的 shared_ptr 。
显然,第2种方法更优雅(对于用户来说),关键是信息怎么存储?
对了, weak_ptr !
实际上, boost 中就是这样实现的。
实现过程
但现在的问题是:何时初始化这个 weak_ptr ?因为类对象生成时还没有生成相应的用来管理这个对象的 shared_ptr 。
boost 1.39.0 中是这样实现的:
首先生成类 A :会依次调用 enable_shared_from_this 的构造函数(定义为 protected),以及类 A 的构造函数。在调用 enable_shared_from_this 的构造函数时,会初始化定义在 enable_shared_from_this 中的 weak_ptr (调用其默认构造函数),这时这个 weak_ptr 是无效的(或者说不指向任何对象)。
接着:外部程序会把指向类 A 对象的指针作为初始化参数来初始化一个 shared_ptr 。
现在来看看 shared_ptr 是如何初始化的,shared_ptr 定义了如下构造函数:
template<class Y>
explicit shared_ptr( Y * p ): px( p ), pn( p )
{
boost::detail::sp_enable_shared_from_this( this, p, p );
}
里面调用了 boost::detail::sp_enable_shared_from_this :
template< class X, class Y, class T >
inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx,
Y const * py, boost::enable_shared_from_this< T > const * pe )
{
if( pe != 0 )
{
pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
}
}
里面又调用了 enable_shared_from_this 的 _internal_accept_owner :
template<class X, class Y> void _internal_accept_owner( shared_ptr<X> const * ppx, Y * py ) const
{
if( weak_this_.expired() )
{
weak_this_ = shared_ptr<T>( *ppx, py );
}
}
而在这里对 enable_shared_from_this 的成员 weak_ptr 进行拷贝赋值,使得整个 weak_ptr 作为类对象 shared_ptr 的一个观察者。
这时,当类对象本身需要自身的 shared_ptr 时,就可以从这个 weak_ptr 来生成一个了。
参考资料
what is the usefulness of enable_shared_from_this
2016-11-02: boost::enable_shared_from_this的更多相关文章
- sicily 1007. To and Fro 2016 11 02
// Problem#: 1007// Submission#: 4893204// The source code is licensed under Creative Commons Attrib ...
- 1036. Crypto Columns 2016 11 02
/* 对于题目多读几遍,然后再关键字排序的时候,把对应的数组序号也排序, EYDE MBLR THAN MEKT ETOE EOTH MEETME B ...
- 【读书笔记】2016.11.19 北航 《GDG 谷歌开发者大会》整理
2016.11.19 周六,我们在 北航参加了<GDG 谷歌开发者大会>,在web专场,聆听了谷歌公司的与会专家的技术分享. 中午免费的午餐,下午精美的下午茶,还有精湛的技术,都是我们队谷 ...
- star ccm+ 11.02安装
STAR CCM+是CD-Adapco公司的主打软件,其安装方式较为简单,这里以图文方式详细描述STAR CCM+11.02安装过程. 1 安装准备工作2 正式安装3 软件破解4 软件测试 1 安装准 ...
- U3D笔记11:47 2016/11/30-15:15 2016/12/19
11:47 2016/11/30Before you can load a level you have to add it to the list of levels used in the gam ...
- 微信iphone7、 ios10播放视频解决方案 2016.11.10
2016.11.10日更新以下方法 微信最新出同层播放规范 即使是官方的也无法解决所有android手机的问题. 另外iphone 5 .5s 某些手机始终会弹出播放,请继续采用 “以下是老的解决办法 ...
- 最新的 cocoapods 安装与使用(2016.11)
cocoapods简介: cocoapods 是iOS的类库管理工具,可以让开发者很方便集成各种第三方库,而不用去网站上一个个下载,再一个个文件夹的拖进项目中,还得添加相关的系统依赖库.只需要安装好c ...
- 【转载】webstorm11(注册,激活,破解,码,一起支持正版,最新可用)(2016.11.16更新)
很多人都发现 http://idea.lanyus.com/ 不能激活了 很多帖子说的 http://15.idea.lanyus.com/ 之类都用不了了 最近封的厉害仅作测试 选择 License ...
- 比特币源码分析--C++11和boost库的应用
比特币源码分析--C++11和boost库的应用 我们先停下探索比特币源码的步伐,来分析一下C++11和boost库在比特币源码中的应用.比特币是一个纯C++编写的项目,用到了C++11和bo ...
随机推荐
- android Sqlite select * from myDatabase没有内容的问题
没什么好说的,但是却在初学的时候弄了很久,百度google查了很多资料.后来才发现,竟然是少了个分号结束符的原因. 开始怀疑人生了...
- pwnable echo2
pwnable echo2 linux 32位程序 涉及FSB和UAF漏洞的利用,先%x泄露地址,然后利用UAF漏洞进行利用 code:
- Linux-awk直接修改原文件
#注意:重定向符号后面的文件名需要加双引号 awk '{print > "file"}' file
- B-index、bitmap-index、text-index使用场景详解
索引的种类:B-tree索引.Bitmap索引.TEXT index1. B-tree索引介绍: B-tree 是一种常见的数据结构,也称多路搜索树,并不是二叉树.B-tree 结构可以显著减少定位 ...
- 症状解决,原因不详的用非默认管理权限账户登录COM注册成功但找不到类型问题
http://social.msdn.microsoft.com/Forums/en-US/11f01ceb-52a4-438f-b7ef-727ce7a3e191/atl-project-in-vs ...
- An invalid character [32] was present in the Cookie value
系统安装Tomcat版本为:tomcat8,登录时报错"An invalid character [32] was present in the Cookie value" 处理方 ...
- net reactor加密源码保软件安全-net reactor使用教程
上一次介绍用 Xenocode Postbuild for .NET 混淆加密源代码确保软件安全,本篇将讨论用 Eziriz .NET Reactor 混淆加密软件源代码,为从未用过该软件加密的用户分 ...
- (转载)iOS开发历程书籍推荐
http://www.zhihu.com/question/19649679 我来说说我学习的过程:(无耻的使用一个回答 回答了很多问题.^^) 第一步,精读 Stephen G. Kochan 的& ...
- IntelliIDEA注册码
[http://idea.lanyus.com/] BIG3CLIK6F-eyJsaWNlbnNlSWQiOiJCSUczQ0xJSzZGIiwibGljZW5zZWVOYW1lIjoibGFuIHl ...
- ngCordova
参见:http://blog.csdn.net/Luo_xinran/article/details/52164480 ngCordova是基于Cordova封装的AngularJS的调用本地设备接口 ...