boost中的智能指针shared_ptr的指针管理
来源:互联网 发布:矩阵潜袭全扩要买哪些 编辑:程序博客网 时间:2024/06/05 00:24
原书44~45页
#include "boost/shared_ptr.hpp" #include <vector> #include <iostream> class A { public: virtual void sing()= protected: virtual ~A() {}; }; class B : public A { public: virtual void sing() { std::cout << "Do re mi fa so la"; } }; boost::shared_ptr<A> createA() { boost::shared_ptr<A> p(new B()); return p; } int main() { typedef std::vector<boost::shared_ptr<A> > container_type; typedef container_type::iterator iterator; container_type container; for (int i=0;i<10;++i) { container.push_back(createA()); } std::cout << "The choir is gathered: \n"; iterator end= for (iterator it=container.begin();it!=end;++it) { (*it)->sing(); } }
上面的例子示范了一个强有力的技术,它涉及 A里面的 protected 析构函数。因为函数 createA 返回的是 shared_ptr<A>, 因此不可能对 shared_ptr::get返回的指针调用 delete 。这意味着如果为了向某个需要裸指针的函数传送裸指针而从 shared_ptr中取出裸指针的话,它不会由于意外地被删除而导致灾难。那么,又是如何允许 shared_ptr 删除它的对象的呢? 这是因为指针指向的真正类型是 B;而 B的析构函数不是protected 的。这是非常有用的方法,用于给shared_ptr中的对象增加额外的安全性。
这句话没有看懂,什么叫“指向的真正类型是B”呢?shared_ptr中不是 T *p么?这明明是指向的A啊,为什么说是指向的B呢?
因为A的析构函数为 protected 的,所以 shared_ptr 类必然不能在其析构函数里调用delete来删除它保存的对象。那么 shared_ptr 究竟是怎么删除它的对象的呢?
好奇心驱使我读了boost关于shared_ptr的源码。从头到尾读了一遍后,竟然没有发现 shared_ptr 的析构函数!因此必然不是在 shared_ptr 的析构函数里删除它的对象。那究竟在哪里呢?
下面是我截取的 shared_ptr 类的实现源码,从中可以窥见一斑:
template<class T> class shared_ptr{private: // Borland 5.5.1 specific workaround typedef shared_ptr<T> this_type;public: ...... typedef typename boost::detail::sp_element< T >::type element_type; ......public: ...... template<class Y> explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete { boost::detail::sp_pointer_construct( this, p, pn ); } ......private: element_type * px; // contained pointer boost::detail::shared_count pn; // reference counter}; // shared_ptr
可以看到,在 shared_ptr 的构造函数,首先将Y *p 赋值给了类成员变量 T* px,然后调用了函数boost::detail::sp_pointer_construct()
template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn ){ boost::detail::shared_count( p ).swap( pn ); ......}
boost::detail::sp_pointer_construct()中调用了shared_count()类,该类是用于管理引用计数的,它的构造函数中的参数 是 Y *p
class shared_count{private: sp_counted_base * pi_; ...... template<class Y> explicit shared_count( Y * p ): pi_( 0 ) { try { pi_ = new sp_counted_impl_p<Y>( p ); } catch(...) { boost::checked_delete( p ); throw; } } ~shared_count() // nothrow { if( pi_ != 0 ) pi_->release(); } ......};
可以看到,在shared_count的构造函数中,使用 Y *p 构造了一个 sp_counted_impl_p 类,在该类的构造函数中,仅仅是将 指针 Y *p 赋值给了成员变量 px_
class sp_counted_base{ ......public: ...... void release() // nothrow { pthread_mutex_lock( &m_ ); long new_use_count = --use_count_; pthread_mutex_unlock( &m_ ); if( new_use_count == 0 ) { dispose(); ...... } } virtual void dispose() = 0; // nothrow ......};template<class X> class sp_counted_impl_p: public sp_counted_base{private: X * px_; ...... explicit sp_counted_impl_p( X * px ): px_( px ) { } virtual void dispose() // nothrow { ...... boost::checked_delete( px_ );...... } ......};
因此,从上面的代码,我们可以很清楚的知道,类 shared_ptr 中 使用 成员变量 boost::detail::shared_count pn 的 成员变量 sp_counted_base * pi_ 的 成员变量 X * px_ 保存了 类型为 Y 的变量 *p,而类 shared_ptr 的成员变量 element_type * px 仅仅指向了 类型为 Y 的变量 *p。
于是,在 类 shared_ptr 析构时,它调用 类 sp_counted_base 的 release()函数,调用了 类sp_counted_impl_p 的dispose()函数的实现,并最终调用到了 boost::checked_delete( px_ ),而我们知道px_的类型是 Y,这也就是为什么 《Beyond the C++ STL》中说 shared_ptr中 “这是因为指针指向的真正类型是 B”。
- boost中的智能指针shared_ptr的指针管理
- Boost智能指针:shared_ptr
- 智能指针boost::shared_ptr
- 智能指针boost::shared_ptr
- Boost智能指针:shared_ptr
- Boost库中的智能指针 shared_ptr智能指针
- Boost智能指针—shared_ptr
- C++ boost智能指针shared_ptr
- boost智能指针系列:shared_ptr
- [6]智能指针boost::shared_ptr
- Boost智能指针shared_ptr、weak_ptr
- 智能指针tr1::shared_ptr、boost::shared_ptr使用
- boost::shared_ptr 智能指针在项目中的使用
- boost智能指针shared_ptr使用要注意的几个问题
- std::auto_ptr boost::shared_ptr智能指针的应用
- Boost智能指针——shared_ptr
- [转载]Boost智能指针——shared_ptr
- Boost智能指针——shared_ptr
- MySQL存储过程详解
- wzplayer for android V1.5.3 (新增YUV文件播放)
- mule配置基础
- 在MSChart中不显示图例标题
- jsp中取得当前时间
- boost中的智能指针shared_ptr的指针管理
- C语言strrev函数
- Compressing my videos 我的视频压缩
- filezilla client代码阅读笔记(一)
- 如何將C#數組傳給具有IntPtr的托管代碼函數?
- 2013年第一季度中国移动互联网应用安全检测与分析报告
- 分享怎样在Win8系统的账号自动登录默认设置技巧
- shell读文件
- 关于typedef的一些用法总结