上一篇:https://blog.csdn.net/qq_41345173/article/details/104270431
BOOST库源码分享,百度网盘提取码:snuc
1.简介
毫无疑问shared_ptr才是最受欢迎的智能指针也是像普通指针的智能指针。常常听说其内部实现是基于引用计数的那么什么是引用计数,其在内部又是怎样实现的今天就让咋来见识一下它的源码,在此之前,先贴一个来自http://www.cplusplus.com/reference/网站的shared_ptr的例子熟悉一下他的具体用法:
#include <iostream>
#include <memory>
#include <boost/shared_ptr.hpp>
using namespace boost;
using namespace std;
int main () {
shared_ptr<int> foo;
shared_ptr<int> bar (new int);
cout << "foo unique?\n" << std::boolalpha;
//boolalpha:一个函数指明以后逻辑真打印为true,否则打印为false
cout << "1: " << foo.unique() << '\n'; // false (empty)
foo = bar;
cout << "2: " << foo.unique() << '\n'; // false (shared with bar)
bar.reset();
cout << "3: " << foo.unique() << '\n'; // true
return 0;
}
输出:
foo unique?
1: false
2: false
3: true
需要特别注意的是shared_ptr由于支持拷贝操作,故可以将他安全的放在标准容器里面了
2.源码分析
template<class T> class shared_ptr
{/*boost\smart_ptr\shared_ptr.hpp*/
private:
typedef shared_ptr<T> this_type;
element_type * px; // contained pointer,element_type等价于类型T
boost::detail::shared_count pn; // reference counter
...
}; // shared_ptr
码量过于巨大,先来康一康私有成员,毕竟成员函数都是围绕着他们转的呀!重点关注引用计数的数据成员shared_count pn
,其私有成员定义如下:
class shared_count
{//boost\smart_ptr\detail\shared_count.hpp
private:
sp_counted_base * pi_; //重点在sp_counted_base类
...
public:
shared_count(): pi_(0) {}
继续向下走关注shared_count的私有成员变量sp_counted_base:
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
int use_count_; // #shared
int weak_count_; // #weak + (#shared != 0)
public:
sp_counted_base(): use_count_( 1 ), weak_count_( 1 ){}//该类唯一构造函数
...
至此已大致清楚了点,若要使用shared_ptr管理资源,根据C++在类中调用构造函数的顺序可知先调用sp_counted_base的构造函数它将成员变量use_count_初始化为1,但是它什么时候调用哩,shared_count的构造函数有多个首先应该调用哪一个哩?以最平常的shared_ptr的构造函数来看:
template<class Y>
explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
{
boost::detail::sp_pointer_construct( this, p, pn );
}
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 );
...
}
显然在这个构造函数里面sp_pointer_construct会调用shared_count的构造函数以new出来的指针为参数创建一个临时的shared_count对象,在如下shared_count的构造函数里面会调用sp_counted_impl_p类的构造函数new出来一个sp_counted_impl_p对象用于初始化pi_成员:
template<class Y> explicit shared_count( Y * p ): pi_( 0 ) {
pi_ = new sp_counted_impl_p<Y>( p );
...
}
瞅一瞅sp_counted_impl_p的构造函数:
template<class X> class sp_counted_impl_p: public sp_counted_base
{
private:
X * px_;
...
public:
explicit sp_counted_impl_p( X * px ): px_( px ){}
...
追踪代码发现sp_counted_impl_p是sp_counted_base的公有派生类,它的自定义私有成员如上,其构造函数仅仅就是用上面的p初始化这个px_,需要注意的是它也会调用基类的构造函数,即刚开始说的sp_counted_base的构造函数初始化use_count_为1。至此这个临时的shared_count以及构造出来了,下一步sp_pointer_construct函数会调用这个临时对象的swap函数,这样就意味着shared_ptr里面的shared_count成员至此完成了自身的构造啦。
3.实现自己的shared_ptr
总结起来就是说先调用shared_ptr对象的构造函数,然后会调用成员变量pn的构造函数初始化它,不过在具体实现的时候略有技巧,下面就仿照上面的流程自己构造一个shared_ptr的基本框架:
#include <iostream>
#include <memory>
#include <string>
using namespace std;
class sp_counted_base
{
private:
sp_counted_base( sp_counted_base const & );
sp_counted_base & operator= ( sp_counted_base const & );
long use_count_; // #shared
public:
sp_counted_base(): use_count_( 1 ){}//该类唯一构造函数
virtual ~sp_counted_base(){
//cout<<"sp_counted_base destroy ..."<<endl;
}
virtual void dispose() = 0;
void release() {
if(--use_count_==0)
{
dispose();
}
}
long use_count() const // nothrow
{
return static_cast<long>( use_count_ );
}
void add_ref_copy()
{
++use_count_;
}
};
template<class X> class sp_counted_impl_p: public sp_counted_base
{
private:
X * px_;
public:
explicit sp_counted_impl_p( X * px ): px_( px ){}
virtual ~sp_counted_impl_p(){
//cout<<"sp_counted_impl_p destroy ..."<<endl;
}
void dispose(){
delete px_;
delete this;
}
};
template<class T> class shared_count
{
private:
sp_counted_base * pi_;
public:
shared_count(T *p):pi_(new sp_counted_impl_p<T>(p)){}
~shared_count(){
if(pi_!=0){
pi_->release();
}
//cout<<"shared_count destroy ..."<<endl;
}
shared_count(shared_count const& r):pi_(r.pi_){
if(pi_){
pi_->add_ref_copy();
}
}
long use_count(){
return pi_!=0?pi_->use_count():0;
}
void swap(shared_count & r){
sp_counted_base *tmp = r.pi_;
r.pi_ = pi_;
pi_ = tmp;
}
};
template<class T> class shared_ptr
{
private:
typedef shared_ptr<T> this_type;
T * px;
shared_count<T> pn; // reference counter
public:
shared_ptr(T *p):px(p),pn(p){}
~shared_ptr(){
//cout<<"shared_ptr destroy ..."<<endl;
}
shared_ptr(shared_ptr const &r):px(r.px),pn(r.pn){}
long use_count(){
return pn.use_count();
}
void swap( shared_ptr & other )
{
std::swap(px, other.px);
pn.swap(other.pn);
}
T & operator* ()const{
return *px;
}
shared_ptr<T>& operator=(shared_ptr<T> const& r){
if(this!=&r){
this_type(r).swap(*this);//巧妙的借助临时对象删除了前面的this对象
}
return *this;
}
}; // shared_ptr
int main () {
shared_ptr<string> foo (new string("Hello World!"));
shared_ptr<string> bar (new string("I'm hero!"));
cout << "foo and bar\n" ;
cout<<"foo_str: "<<*foo<<"; bar_str: "<<*bar<<endl;
cout<<"foo_use_count: "<<foo.use_count()<<"; bar_use_count: "<<bar.use_count()<<endl;
foo.swap(bar);
cout<<"foo_str: "<<*foo<<"; bar_str: "<<*bar<<endl;
foo = bar;
cout<<"foo_str: "<<*foo<<"; bar_str: "<<*bar<<endl;
cout<<"foo_use_count: "<<foo.use_count()<<"; bar_use_count: "<<bar.use_count()<<endl;
return 0;
}
输出:
foo and bar
foo_str: Hello World!; bar_str: I'm hero!
foo_use_count: 1; bar_use_count: 1
foo_str: I'm hero!; bar_str: Hello World!
foo_str: Hello World!; bar_str: Hello World!
foo_use_count: 2; bar_use_count: 2
好了,以上就是shared_ptr这个指针在boost库里面的简单实现,当然还有很多成员函数没有编写出了,若敢兴趣可以下载boost库源码剖析之。明白shared_ptr类是基础,shared_count类是计数类,其通过类sp_counted_base管理真正的指针使用计数,其内部定义有管理use_count_变量的函数。