intrusive_ptr源码分析

intrusive_ptr是一个侵入式的引用计数型智能指针,它可以用于以下两种情形:

  • 对内存占用要求非常严格,要求必须与原始指针一样
  • 现存代码已经有了引用计数机制管理的对象

boost库不推荐使用intrusive_ptr,因为shared_ptr已经非常强大且灵活,工作足够好,可以满足绝大部分的需要。

下面来看一下intrusive的源码:

template<class T> class intrusive_ptr
{
private:
    typedef intrusive_ptr this_type;
public:
    typedef T element_type;

    intrusive_ptr() BOOST_NOEXCEPT : px( 0 )
    {
    }

    intrusive_ptr( T * p, bool add_ref = true ): px( p )
    {
        if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
    }

    intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
    {
        if( px != 0 ) intrusive_ptr_add_ref( px );
    }

    ~intrusive_ptr()
    {
        if( px != 0 ) intrusive_ptr_release( px );
    }

    // Move support
    //支持C++11移动构造,此处省略

    intrusive_ptr & operator=(intrusive_ptr const & rhs)
    {
        this_type(rhs).swap(*this);
        return *this;
    }

    intrusive_ptr & operator=(T * rhs)
    {
        this_type(rhs).swap(*this);
        return *this;
    }

    void reset() BOOST_NOEXCEPT
    {
        this_type().swap( *this );
    }

    void reset( T * rhs )
    {
        this_type( rhs ).swap( *this );
    }

    T * get() const BOOST_NOEXCEPT
    {
        return px;
    }

    T & operator*() const
    {
        BOOST_ASSERT( px != 0 );
        return *px;
    }

    T * operator->() const
    {
        BOOST_ASSERT( px != 0 );
        return px;
    }

// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>

    void swap(intrusive_ptr & rhs) BOOST_NOEXCEPT
    {
        T * tmp = px;
        px = rhs.px;
        rhs.px = tmp;
    }

private:

    T * px;
};

呵呵,非常简单,就是这么一点。但是我们发现,intrusive_ptr的构造析构等函数中,都使用了所管理的指针,以其作为参数执行某个函数。但实际上,这些函数是没有定义的。需要我们自己定义。

因为这几个函数的源码是这样的:

template< typename DerivedT, typename CounterPolicyT >
void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
template< typename DerivedT, typename CounterPolicyT >
void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;

呵,只有声明。

所以我们在使用intrusive_ptr是要自己提供引用计数,这就叫侵入式。我们可以在要管理的对象内部使用友元函数来实现上面那两个函数,执行计数器的加或减。但是通常我们会采用继承的方式实现,实现一个引用计数器基类,提供intrusive_ptr_add_ref()和intrusive_ptr_release()两个函数,然后继承它即可。

示例代码如下:

#include <iostream>
#include <boost/intrusive_ptr.hpp>

class reference_counter {
  int ref_count_;
public:
    reference_counter() : ref_count_(0) {}

    virtual ~reference_counter() {}

    friend void intrusive_ptr_add_ref(reference_counter *p) { 
      ++p->ref_count_;
    }   

    friend void intrusive_ptr_release(reference_counter *p) {
      if(--p->ref_count_)
        delete p;
    }   
    /*  error
    int use_count() {
        return ref_count_;
    }
    */
protected:
    reference_counter& operator=(const reference_counter&) {
    // 无操作
      return *this;
    }   
private:
    // 禁止复制构造函数
reference_counter(const reference_counter&); 
};

class some_class : public reference_counter {
public:
  some_class() {
    std::cout << "some_class::some_class()\n";
  }

  some_class(const some_class& other) {
    std::cout << "some_class(const some_class& other)\n";
  }

  ~some_class() {
    std::cout << "some_class::~some_class()\n";
  }
};

int main()
{
  std::cout << "Before start of scope\n";
  {
    boost::intrusive_ptr<some_class> p1(new some_class());
    boost::intrusive_ptr<some_class> p2(p1);
    //std::cout<<p2.use_count()<<std::endl;
  }
  std::cout << "After end of scope \n";
}

输出:

这里写图片描述

由于intrusive_ptr源码(上面已经给了)中不提供use_count()这个成员函数,所以我们也无法获得use_count值。

也许这样用你会觉得麻烦,不过实际上,boost中已经为我们实现了一个引用计数器的基类,我们使用intrusive_ptr时,继承该类就无需自己再费神了。

boost库中的引用计数基类是这样的:

template< typename DerivedT, typename CounterPolicyT >
class intrusive_ref_counter
{
private:
    //! Reference counter type
    typedef typename CounterPolicyT::type counter_type;
    //! Reference counter
    mutable counter_type m_ref_counter;

public:
    /*!
     * Default constructor
     *
     * \post <tt>use_count() == 0</tt>
     */
    intrusive_ref_counter() BOOST_NOEXCEPT : m_ref_counter(0)
    {
    }

    /*!
     * Copy constructor
     *
     * \post <tt>use_count() == 0</tt>
     */
    intrusive_ref_counter(intrusive_ref_counter const&) BOOST_NOEXCEPT : m_ref_counter(0)
    {
    }

    /*!
     * Assignment
     *
     * \post The reference counter is not modified after assignment
     */
    intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_NOEXCEPT { return *this; }

    /*!
     * \return The reference counter
     */
    unsigned int use_count() const BOOST_NOEXCEPT
    {
        return CounterPolicyT::load(m_ref_counter);
    }

protected:
    /*!
     * Destructor
     */
    BOOST_DEFAULTED_FUNCTION(~intrusive_ref_counter(), {})

    friend void intrusive_ptr_add_ref< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
    friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_NOEXCEPT;
};

唉,上面这些就是intrusive_ptr的用法,有点蛋疼。不过却是让人感觉很叼的样子。侵入式的智能指针,相比shared_ptr,不需要虚函数的开销,确实性能强一些。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值