boost::intrusive_ptr原理介绍
boost::intrusive_ptr一种“侵入式”的引用计数指针,它实际并不提供引用计数功能,而是要求被存储的对象自己实现引用计数功能,并提供intrusive_ptr_add_ref和intrusive_ptr_release函数接口供boost::intrusive_ptr调用。
下面通过一个具体的例子来说明boost::intrusive_ptr的用法,首先实现一个基类intrusive_ptr_base,定义intrusive_ptr_add_ref和intrusive_ptr_release函数来提供引用计数功能。
/** * intrusive_ptr_base基类,提供intrusive_ptr_add_ref()和intrusive_ptr_release()函数来提供引用计数功能; * 使用boost::intrusive_ptr指针存储的用户类类型必须继承自intrusive_ptr_base基类。 */ #include <ostream> #include <boost/checked_delete.hpp> #include <boost/detail/atomic_count.hpp> template<class T> class intrusive_ptr_base { public: /** * 缺省构造函数 */ intrusive_ptr_base(): ref_count(0) { std::cout << " Default constructor " << std::endl; } /** * 不允许拷贝构造,只能使用intrusive_ptr来构造另一个intrusive_ptr */ intrusive_ptr_base(intrusive_ptr_base<T> const&): ref_count(0) { std::cout << " Copy constructor..." << std::endl; } /** * 不允许进行赋值操作 */ intrusive_ptr_base& operator=(intrusive_ptr_base const& rhs) { std::cout << " Assignment operator..." << std::endl; return *this; } /** * 递增引用计数(放到基类中以便compiler能找到,否则需要放到boost名字空间中) */ friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s) { std::cout << " intrusive_ptr_add_ref..." << std::endl; assert(s->ref_count >= 0); assert(s != 0); ++s->ref_count; } /** * 递减引用计数 */ friend void intrusive_ptr_release(intrusive_ptr_base<T> const* s) { std::cout << " intrusive_ptr_release..." << std::endl; assert(s->ref_count > 0); assert(s != 0); if (--s->ref_count == 0) boost::checked_delete(static_cast<T const*>(s)); //s的实际类型就是T,intrusive_ptr_base<T>为基类 } /** * 类似于shared_from_this()函数 */ boost::intrusive_ptr<T> self() { return boost::intrusive_ptr<T>((T*)this); } boost::intrusive_ptr<const T> self() const { return boost::intrusive_ptr<const T>((T const*)this); } int refcount() const { return ref_count; } private: ///should be modifiable even from const intrusive_ptr objects mutable boost::detail::atomic_count ref_count; };
用户类类型需要继承intrusive_ptr_base基类,以便具有引用计数功能。
#include <iostream> #include <string> #include <boost/intrusive_ptr.hpp> #include "intrusive_ptr_base.hpp" /** * 用户类类型继承自intrusive_ptr_base,该实现方式类似于boost::enable_shared_from_this<Y> */ class Connection : public intrusive_ptr_base< Connection > { public: /** * 构造函数,调用intrusive_ptr_base< Connection >的缺省构造函数来初始化对象的基类部分 */ Connection(int id, std::string tag): connection_id( id ), connection_tag( tag ) {} /** * 拷贝构造函数,只复制自身数据,不能复制引用计数部分 */ Connection(const Connection& rhs): connection_id( rhs.connection_id ), connection_tag( rhs.connection_tag) {} /** * 赋值操作,同样不能复制引用计数部分 */ const Connection operator=( const Connection& rhs) { if (this != &rhs) { connection_id = rhs.connection_id; connection_tag = rhs.connection_tag; } return *this; } private: int connection_id; std::string connection_tag; }; int main() { std::cout << "Create an intrusive ptr" << std::endl; boost::intrusive_ptr< Connection > con0 (new Connection(4, "sss") ); //调用intrusive_ptr_add_ref()递增引用计数 std::cout << "Create an intrusive ptr. Refcount = " << con0->refcount() << std::endl; boost::intrusive_ptr< Connection > con1 (con0); //调用intrusive_ptr_add_ref() std::cout << "Create an intrusive ptr. Refcount = " << con1->refcount() << std::endl; boost::intrusive_ptr< Connection > con2 = con0; //调用intrusive_ptr_add_ref() std::cout << "Create an intrusive ptr. Refcount = " << con2->refcount() << std::endl; std::cout << "Destroy an intrusive ptr" << std::endl; return 0; }
程序运行输出:
Create an intrusive ptr
Default constructor
intrusive_ptr_add_ref...
Create an intrusive ptr. Refcount = 1
intrusive_ptr_add_ref...
Create an intrusive ptr. Refcount = 2
intrusive_ptr_add_ref...
Create an intrusive ptr. Refcount = 3
Destroy an intrusive ptr
intrusive_ptr_release...
intrusive_ptr_release...
intrusive_ptr_release...
对比boost::shared_ptr
使用boost::shared_ptr用户类本省不需要具有引用计数功能,而是由boost::shared_ptr来提供;使用boost::shared_ptr的一大陷阱就是用一个raw pointer多次创建boost::shared_ptr,这将导致该raw pointer被多次销毁当boost::shared_ptr析构时。即不能如下使用:
那么为什么通常鼓励大家使用shared_ptr,而不是intrusive_ptr呢, 在于shared_ptr不是侵入性的,可以指向任意类型的对象; 而intrusive_ptr所要指向的对象,需要继承intrusive_ptr_base,即使不需要,引用计数成员也会被创建。
原文地址: