boost中的智能指针shared_ptr的指针管理
2013-06-26 15:05
447 查看
最近在阅读《Beyond the C++ STL》一书的shared_ptr一章时,遇到点困惑,记录如下:
原书44~45页
上面的例子示范了一个强有力的技术,它涉及 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 类的实现源码,从中可以窥见一斑:
可以看到,在 shared_ptr 的构造函数,首先将Y *p 赋值给了类成员变量 T* px,然后调用了函数boost::detail::sp_pointer_construct()
boost::detail::sp_pointer_construct()中调用了shared_count()类,该类是用于管理引用计数的,它的构造函数中的参数 是 Y *p
可以看到,在shared_count的构造函数中,使用 Y *p 构造了一个 sp_counted_impl_p 类,在该类的构造函数中,仅仅是将 指针 Y *p 赋值给了成员变量 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”。
原书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”。
相关文章推荐
- [置顶] 从零开始学C++之boost库(一):详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)
- boost 智能指针 shared_ptr 原理分析
- 智能指针tr1::shared_ptr、boost::shared_ptr使用
- C++中的资源管理(一):构造自己的auto_ptr与shared_ptr智能指针
- Boost智能指针——weak_ptr vs shared_ptr
- Boost智能指针——shared_ptr
- [5] 智能指针boost::shared_ptr
- Boost智能指针——shared_ptr
- Boost智能指针——scoped_ptr、shared_ptr、weak_ptr、intrusive_ptr
- 【Boost】boost库中智能指针——shared_ptr
- 动态内存管理和智能指针 2.0 -- shared_ptr
- 详解 boost 库智能指针(scoped_ptr<T> 、shared_ptr<T> 、weak_ptr<T> 源码分析)
- boost::shared_ptr 智能指针在项目中的使用
- 几种智能指针的比较(std::auto_ptr、boost::scoped_ptr、boost::shared_ptr、boost::weak_ptr)
- std::auto_ptr boost::shared_ptr智能指针的应用
- Boost 智能指针错误shared_ptr Assertion px != 0 failed
- boost::shared_ptr智能指针分析
- Boost智能指针——shared_ptr
- 关于boost 库 shared_ptr 智能指针的循环引用【2013.10.22】
- 浅析boost之智能指针—shared_ptr