您的位置:首页 > 其它

intrusive_ptr源码分析

2017-01-22 18:36 197 查看
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,不需要虚函数的开销,确实性能强一些。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息