Boost 关于 shared_ptr 的学习心得

今天学习了boost 的智能指针中的shared_ptr,感觉收获颇多,现在就写下来,一则作为学习笔记,二则与大家分享我的学习心得

shared_ptr智能指针我想大家如果看过《C++Primer》第四版(16.5 A generic handle class 一个泛型句柄)的话,应该了解作者构造了一个通过引用计数的方法来管理指针的,

没错shared_ptr 同样是这样实现的,首先先看一下书中的实现:


看完上面的代码我想你应该了解智能指针是如何工作的了吧,看过书本的可以当做一次复习;

对于shard_ptr的结构如何使用我想我不用做过多介绍,看一下头文件再结合文档和网上的一些资料应该很快就明白

下面我展示一下shared_ptr的一个用法:

#include <iostream>
#include "boost/shared_ptr.hpp"
using namespace std;
using namespace boost;
class A
{
	public:
	A(){}
    virtual  void mem_func() = 0;
   protected:
   virtual ~A()
   {
      cout<<"A's dector\n";
   }

	private:

};

class B:public A
{
	public:
	B(){}
	virtual void mem_func()
	{
	   cout<<"I'm mem_fun\n";
	}

};
shared_ptr<A> create()
{
   return shared_ptr<A>(new B);
}
int main()
{
       shared_ptr<A> sp = create();
       sp->mem_func();
      return 0;
}

请注意,上面的代码,A的析构函数被定义为protect,而它在程序结束时候被调用了,这个就是我要将的地方了,我们通过源码来分析一下

首先shared_ptr在内部有两个私有成员:

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

其中 px是原生的指针,也就是 new B 得到的指针,但是他是A * 类型的,shared_ptr通过它来快速访问内存,shared_ptr重载* , ->来让用户像使用原生指针一样来使用,

但是在删除这块内存时,shared_ptr不是直接这样 delete px的,因为~A 是protect,这样释放内存会报错,你可是测试一下的代码就知道了

A * pa = new B;

delete pa;

编译器会报错如:

而你这样定义 A  a同样也编译不过,但是前面的代码明明调用了基类A 的析构函数 打印出了 A‘ dector,不急,往下看pn 这个变量

 pn 这个东东就大有来头了,要完全弄懂,我想我还没那能力,里面涉及到了一些平台相关的知识,我只讲为何会跳用了~A;

其实跟踪pn 可以发现它是:shared_count 类型,它保存一个计数值,也就是如C++Primer中的那个 user ,但是它还保存有一个指针

就是在构造shared_ptr的时候传就去的那个new B,注意是B *类型的指针,px保存的是A* 基类的指针,当pn 的计数值为0的是后就会

delete这个指针,可以看一下shared_ptr的一个构造函数你就会明白它是如何工作的了:

  template<class T>

class shared_ptr{

.............

public:

..........

    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 );
    }

...........

private:

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

};

请注意 在 shared_ptr<A>(new B)中,模板类型 T *是 一个 A * , shared_ptr调用的是一个模板构造函数shared_ptr( Y * p )中的Y* 是 B*,而px(p)

等价于 A* px = B* p ,而对于pn,下面是我从源代码里面复制出来的一个pn的构造构造函数头

    template<class Y> explicit shared_count( Y * p ): pi_( 0 )
#if defined(BOOST_SP_ENABLE_DEBUG_HOOKS)
        , id_(shared_count_id)

可以看到pn也是一个模板,传递过来的 Y * p 就是 就是 shared_ptr<A>(new B)中的new B 了,当计数器为0是就会析构掉这个B* 指针,所以可以知道

其实px与pn内保持的指针类型是不一样的,px 的是A* 而 pn的是 A 的子类 B 的指针,这样       B* pb = new B;    delete pb;是妹问题的。

对于pn 里面复杂的实现我暂时还没能完全理解,有时间再慢慢研究,感兴趣的可以自己去看源代码


全文完!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值