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

 

posted on 2020-08-12 00:04  xgcode  阅读(284)  评论(0编辑  收藏  举报