intrusive_ptr源码分析

来源:互联网 发布:青岛太阳软件 编辑:程序博客网 时间:2024/06/02 17:52

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 0
原创粉丝点击