您的位置:首页 > 其它

boost shared_ptr实现浅析

2011-11-06 20:06 253 查看
版本boost 1.43.0

头文件<boost/shared_ptr.hpp>

shared_ptr是boost中最强大的智能指针,基于C++非常精巧的实现了“引用计数”的功能

shared_ptr只有两个类成员变量

T * px;                     // contained pointer
boost::detail::shared_count pn;    // reference counter


px是指向实际对象的指针,而pn就是用来计数的类了。

原来一直很好奇shared_ptr是如何在不同对象中共享引用计数的,其实很简单,shared_count类可以看成是一个指向计数器的指针,

不同的shared_ptr类都指向同一个计数器地址,这样就达到共享的目的了。

再从代码级别来详细了解一下

shared_count只有一个成员变量

sp_counted_base * pi_;


pi_实际是一个指向sp_counted_base的子类sp_counted_impl_p*(*由编译选项确定),

一般来说,sp_counted_base中实现了add_ref_copy和release这些对引用计数操作的接口,而sp_counted_impl_p*则实现了allocator和deallocator这些接口

值得注意的是add_ref_copy和release都是“原子”操作,所以针对不同平台有不同的sp_counted_base实现,这个类似kernel里的atomic_t

再来看下shared_ptr的赋值操作
shared_ptr & operator=( shared_ptr && r ) // never throws
{
this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
return *this;
}


this_type( static_cast< shared_ptr && >( r ) )生成一个临时对象,然后和this交换,注意就是这个临时对象给引用计数加1了。

swap函数的实现如下
void swap(shared_ptr<T> & other) // never throws
{
std::swap(px, other.px);
pn.swap(other.pn);
}
px的swap很简单,pn的swap调用了shared_count自定义的swap函数,实现如下
void swap(shared_count & r) // nothrow
{
sp_counted_base * tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}


这里只是交换了“引用计数”的指针。

临时对象在构造的时候是如何增加引用计数的呢?考虑如下场景
shared_ptr<T> ptr1(new T);
shared_ptr<T> ptr2(ptr1);


再来看看shared_ptr的代码是如何实现的
template<class Y>
explicit shared_ptr( Y * p ): px( p ), pn( p ) // Y must be complete
{
boost::detail::sp_enable_shared_from_this( this, p, p );
}


可以看到这里px和pn调用的都是赋值操作,px自不必说,pn的赋值函数如下
shared_count & operator= (shared_count const & r) // nothrow
{
sp_counted_base * tmp = r.pi_;

if( tmp != pi_ )
{
if( tmp != 0 ) tmp->add_ref_copy();
if( pi_ != 0 ) pi_->release();
pi_ = tmp;
}

return *this;
}


这里很明显原来的计数被release,而新的计数被add_ref_copy了
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: