c++学习系列(2)---shared_ptr的实现和代码例子版本0.2
本文主要介绍: shared_ptr中为什么需要enable_shared_from_this 这个基类,以及shared_ptr中是如何实现这个功能的。代码中如何实现。
问题1: 代码中为什么需要enable_shared_from_this 这个基类。在类对象内部需要生成一个共享指针;如下:
#include<iostream> #include<memory> using namespace std; class base{ public: base(){} ~base(){cout<<"destruct"<<endl;} shared_ptr<base> get_ptr(){return shared_ptr<base>(this);} }; int main(){ shared_ptr<base> pdata1(new base); shared_ptr<base> pdata2 = pdata1->get_ptr(); return 0; }
在这种情况下,就会存在内存的重复释放。执行结果如下:
修改代码如下就可以避免对象重复释放的情况:
#include<iostream> #include<memory> using namespace std; class base:public enable_shared_from_this<base> { public: base(){} ~base(){cout<<"destruct"<<endl;} shared_ptr<base> get_ptr(){return shared_from_this();} }; int main(){ shared_ptr<base> pdata1(new base); shared_ptr<base> pdata2 = pdata1->get_ptr(); return 0; }
这种情况下就不会存在内存重复释放的的情况。
问题2: shared_ptr是如何实现这个enable_shared_from_this 这个功能。
查看boost源码:enable_shared_from_this 中有一个weak_ptr的成员。在构造share_ptr的构造函数中,会加载函数sp_pointer_construct ,这个函数会调用sp_enable_shared_from_this,share_ptr 中实现了两个sp_enable_shared_from_this,具体的声明如下:
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_enable_shared_from_this( ppx, p, p ); } 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 ) ); } } inline void sp_enable_shared_from_this( ... ) { }
其中指针p是 智能指针指向的对象,如果该对象没有继承基类对象enable_shared_from_this,则会调用一个空函数 sp_enable_shared_from_this。c++11利用了重载的特性,巧妙的实现了这个特性。可以看一个sample如下:
#include<iostream> #include<memory> using namespace std; class Node{ }; class Nodederive:public Node{ }; class base { public: base(Nodederive* pdata){process_node(pdata);} ~base(){cout<<"destruct"<<endl;} void process_node(Node* pdata){cout<<"node process"<<endl;} void process_node(...){cout<<"nothging"<<endl;} }; int main(){ Nodederive node; shared_ptr<base> pdata1(new base(&node)); return 0; }
如果 类Nodederive不继承Node的话,则构造函数会调用 process_node(...)函数。
因此结论是,在实现shared_ptr接口的时候,要声重载sp_enable_shared_from_this 函数。
代码见https://github.com/wudafucode/cc/tree/master/shared_ptr