1、概述

intrusive_ptr类模板存储了一个指向一个引用计数的对象的指针。每一个 intrusive_ptr 实例都会通过对函数 intrusive_ptr_add_ref 的调用来增加引用计数,并将指针作为参数传递给它。同样,当intrusive_ptr实例被销毁时,它会调用intrusive_ptr_release函数;当对象的引用计数为零时,这个函数会销毁对象。要求用户提供这两个函数的正确的实现。

在支持参数依赖性查找的编译器上,intrusive_ptr_add_ref和intrusive_ptr_release应该在与其参数相对应的命名空间中定义;否则,这些定义需要放到命名空间boost中。boost库提供了一个辅助基类模板 intrusive_ref_counter,基于intrusive_ref_counter可以让自己定义的类支持intrusive_ptr。

intrusive_ptr<T>可以隐式转换为intrusive_ptr<U>,只要T*可以隐式转换为U*,这种“向上”的转换很方便,很nice.

2、为什么要使用intrusive_ptr呢?为什么不使用shared_ptr、unique_ptr、scoped_ptr呢?主要原因如下:

1、一些现有的框架或软件已经提供了内嵌引用计数的对象。

2、intrusive_ptr的内存占用与相应的原始指针相同。

3、intrusive_ptr<T>可以从一个任意的T*类型的裸指针构造,可以构造任意多个intrusive_ptr<T>而不会发生重复释放的问题(shared_ptr<T>如果从裸指针构造则会发生重复释放的问题)。

4、作为一般规则,如果并不确定intrusive_ptr比shared_ptr更合适,那么请优先使用shared_ptr,因为intrusive_ptr是对shared_ptr的一种补足。

3、内部实现

intrusive_ptr.hpp

template<class T> class intrusive_ptr
{
private:typedef intrusive_ptr this_type;public:typedef T element_type;BOOST_CONSTEXPR intrusive_ptr() BOOST_SP_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<U> const & rhs ) : px( rhs.get() ){if( px != 0 ) 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 );}template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs){this_type(rhs).swap(*this);return *this;}// Move support#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )intrusive_ptr(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT : px( rhs.px ){rhs.px = 0;}intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT{this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);return *this;}template<class U> friend class intrusive_ptr;template<class U>intrusive_ptr(intrusive_ptr<U> && rhs): px( rhs.px ){rhs.px = 0;}template<class U>intrusive_ptr & operator=(intrusive_ptr<U> && rhs) BOOST_SP_NOEXCEPT{this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);return *this;}#endifintrusive_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(){this_type().swap( *this );}void reset( T * rhs ){this_type( rhs ).swap( *this );}void reset( T * rhs, bool add_ref ){this_type( rhs, add_ref ).swap( *this );}T * get() const BOOST_SP_NOEXCEPT{return px;}T * detach() BOOST_SP_NOEXCEPT{T * ret = px;px = 0;return ret;}T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT{BOOST_ASSERT( px != 0 );return *px;}T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT{BOOST_ASSERT( px != 0 );return px;}// implicit conversion to "bool"
#include <boost/smart_ptr/detail/operator_bool.hpp>void swap(intrusive_ptr & rhs) BOOST_SP_NOEXCEPT{T * tmp = px;px = rhs.px;rhs.px = tmp;}private:T * px;
};template<class T, class U>bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;template<class T, class U>bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept;template<class T, class U>bool operator==(intrusive_ptr<T> const & a, U * b) noexcept;template<class T, class U>bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept;template<class T, class U>bool operator==(T * a, intrusive_ptr<U> const & b) noexcept;template<class T, class U>bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept;template<class T>bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept;template<class T> void swap(intrusive_ptr<T> & a, intrusive_ptr<T> & b) noexcept;template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept;template<class T, class U>intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & r) noexcept;template<class T, class U>intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & r) noexcept;template<class T, class U>intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & r) noexcept;template<class E, class T, class Y>std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os,intrusive_ptr<Y> const & p);
}

从代码可以看出,boost::intrusive_ptr<T>的实现非常之简单,下面做一下简单的解读:

1、T* px;声明一个T类型的裸指针,用于持有指针数据;

2、拷贝构造函数、析构函数是boost::intrusive_ptr<T>的核心函数,分别调用了intrusive_ptr_add_ref()和intrusive_release()函数,实现了引用计数的增加、减少及释放;

3、intrusive_ptr还支持了Move语义;

4、其他的一些函数,如:get、reset、detach为了方便使用;

当然,上面只是一部分的实现,接下来,我们看一下intrusive_ref_counter的实现

/*!* \brief Thread unsafe reference counter policy for \c intrusive_ref_counter** The policy instructs the \c intrusive_ref_counter base class to implement* a reference counter suitable for single threaded use only. Pointers to the same* object with this kind of reference counter must not be used by different threads.*/
struct thread_unsafe_counter
{typedef unsigned int type;static unsigned int load(unsigned int const& counter) BOOST_SP_NOEXCEPT{return counter;}static void increment(unsigned int& counter) BOOST_SP_NOEXCEPT{++counter;}static unsigned int decrement(unsigned int& counter) BOOST_SP_NOEXCEPT{return --counter;}
};/*!* \brief Thread safe reference counter policy for \c intrusive_ref_counter** The policy instructs the \c intrusive_ref_counter base class to implement* a thread-safe reference counter, if the target platform supports multithreading.*/
struct thread_safe_counter
{typedef boost::detail::atomic_count type;static unsigned int load(boost::detail::atomic_count const& counter) BOOST_SP_NOEXCEPT{return static_cast< unsigned int >(static_cast< long >(counter));}static void increment(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT{++counter;}static unsigned int decrement(boost::detail::atomic_count& counter) BOOST_SP_NOEXCEPT{return static_cast< unsigned int >(--counter);}
};template< typename DerivedT, typename CounterPolicyT = thread_safe_counter >
class intrusive_ref_counter;template< typename DerivedT, typename CounterPolicyT >
void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
template< typename DerivedT, typename CounterPolicyT >
void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;/*!* \brief A reference counter base class** This base class can be used with user-defined classes to add support* for \c intrusive_ptr. The class contains a reference counter defined by the \c CounterPolicyT.* Upon releasing the last \c intrusive_ptr referencing the object* derived from the \c intrusive_ref_counter class, operator \c delete* is automatically called on the pointer to the object.** The other template parameter, \c DerivedT, is the user's class that derives from \c intrusive_ref_counter.*/
template< typename DerivedT, typename CounterPolicyT >
class intrusive_ref_counter
{
private://! Reference counter typetypedef typename CounterPolicyT::type counter_type;//! Reference countermutable counter_type m_ref_counter;public:/*!* Default constructor** \post <tt>use_count() == 0</tt>*/intrusive_ref_counter() BOOST_SP_NOEXCEPT : m_ref_counter(0){}/*!* Copy constructor** \post <tt>use_count() == 0</tt>*/intrusive_ref_counter(intrusive_ref_counter const&) BOOST_SP_NOEXCEPT : m_ref_counter(0){}/*!* Assignment** \post The reference counter is not modified after assignment*/intrusive_ref_counter& operator= (intrusive_ref_counter const&) BOOST_SP_NOEXCEPT { return *this; }/*!* \return The reference counter*/unsigned int use_count() const BOOST_SP_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_SP_NOEXCEPT;friend void intrusive_ptr_release< DerivedT, CounterPolicyT >(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT;
};template< typename DerivedT, typename CounterPolicyT >
inline void intrusive_ptr_add_ref(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
{CounterPolicyT::increment(p->m_ref_counter);
}template< typename DerivedT, typename CounterPolicyT >
inline void intrusive_ptr_release(const intrusive_ref_counter< DerivedT, CounterPolicyT >* p) BOOST_SP_NOEXCEPT
{if (CounterPolicyT::decrement(p->m_ref_counter) == 0)delete static_cast< const DerivedT* >(p);
}} // namespace sp_adl_blockusing sp_adl_block::intrusive_ref_counter;
using sp_adl_block::thread_unsafe_counter;
using sp_adl_block::thread_safe_counter;} // namespace boost#if defined(_MSC_VER)
#pragma warning(pop)
#endif#endif // BOOST_SMART_PTR_INTRUSIVE_REF_COUNTER_HPP_INCLUDED_

上面代码中,有三个最关键的类型,分别是:thread_unsafe_counter、thread_safe_counter和intrusive_ref_counter:

1、两个计数策略:thread_unsafe_counter和thread_safe_counter分别实现了线程不安全的和线程安全的引用计数,内部均有一个引用计数成员——counter,实现了counter的++和--操作;

2、intrusive_ref_counter则通过模板参数,使用了上述的thread_unsafe_counter和thread_safe_counter,在没有指定CounterPolicyT的情况下,默认使用的是thread_safe_counter。

有两个最关键的函数,分别是:intrusive_ptr_add_ref和intrusive_ptr_release:

1、intrusive_ptr_add_ref函数,实现了增加引用计数,在boost::intrusive_ptr<T>的copy constructor中调用;

2、intrusive_ptr_release函数,实现了减少引用计数,当引用计数减少到0的时候,则释放对象;

PS:

1、从上面intrusive_ptr_release函数的代码可以看出,释放对象用的是delete操作符,所以intrusive_ptr不可以持有数组对象,否则会造成内存泄漏。

2、从实现上来看,比shared_ptr的内部实现简单多了,前几年有幸了解过shared_ptr的内部实现,以后有机会把内部实现的原理也讲一下(并不仅仅是简单的引用计数那么简单)。

3、一般情况下,当我们自己定义的class或struct需要支持boost::intrusive_ptr<T>时,只需要从boost::intrusive_ref_counter继承即可,不需要写任何多余的函数,因为boost已经帮我们实现了,示例如下:

class smarter:public boost::intrusive_ref_counter<smarter,boost::thread_safe_counter>
{
public:smarter(){}virtual ~smarter()=default;boost::intrusive_ptr<smarter> self(){//此函数仅仅是为了方便的从对象生成intrusive_ptr,比如:从栈对象上生成一个intrusive_ptrreturn boost::intrusive_ptr<smarter>(this);}
};

C++智能指针之——boost::intrusive_ptr<T>的内部实现相关推荐

  1. C++智指针之——boost::intrusive_ptr,一种与shared_ptr、unique_ptr截然不同的智能指针

    智能指针boost::shared_ptr/std::shared_ptr使用了和数据无关的引用计数,在使用shared_ptr之前,必须要搞清楚资源的所有权和资源的使用权这两个问题(详见<C+ ...

  2. boost any 实现万能容器_全面剖析 C++ Boost 智能指针!| CSDN 博文精选

    作者 | .NY&XX 责编 | 屠敏 出品 | CSDN 博客 为什么要使用智能指针 C++没有提供类似JAVA的垃圾回收机制,因此Boost可以通过智能指针来管理内存避免一些问题.C++继 ...

  3. 全面剖析 C++ Boost 智能指针! | CSDN 博文精选

    作者 | .NY&XX 责编 | 屠敏 出品 | CSDN 博客 为什么要使用智能指针 C++没有提供类似JAVA的垃圾回收机制,因此Boost可以通过智能指针来管理内存避免一些问题.C++继 ...

  4. C++智能指针剖析(上)std::auto_ptr与boost::scoped_ptr

    1. 引入 C++语言中的动态内存分配没有自动回收机制,动态开辟的空间需要用户自己来维护,在出函数作用域或者程序正常退出前必须释放掉. 即程序员每次 new 出来的内存都要手动 delete,否则会造 ...

  5. C++ 智能指针详解

    智能指针内容很多,重点是基本用法. #include <boost/shared_ptr.hpp> class CBase: public boost::enable_shared_fro ...

  6. [zz] C++智能指针循环引用解决

    转载自:http://blog.csdn.net/segen_jaa/article/details/8080167 参考文章:http://www.cnblogs.com/TianFang/arch ...

  7. 智能指针 shared_ptr 解析

    近期正在进行<Effective C++>的第二遍阅读,书里面多个条款涉及到了shared_ptr智能指针,介绍的太分散,学习起来麻烦.写篇blog整理一下. LinJM   @HQU s ...

  8. C++ — 智能指针的简单实现以及循环引用问题

    http://blog.csdn.net/dawn_sf/article/details/70168930 智能指针 _________________________________________ ...

  9. 智能指针变量做函数参数的一个值得注意的地方

    作者:朱金灿 来源:http://blog.csdn.net/clever101 先考考大家,下面一段程序,会有什么问题: #include <iostream> #include < ...

最新文章

  1. Xamarin.Forms教程开发的Xcode的下载安装
  2. 【Linux】一步一步学Linux——which命令(45)
  3. Bash shell的内建命令:type
  4. mysql 核对_核对数据库表记录的shell脚本
  5. 资深工程师为何否定这种单例模式
  6. 做简单的android 软件推荐,Android_适用于Android开发的简单聊天软件,适用于android 开发。是一个简 - phpStudy...
  7. 将结构体数据存储到一段字符串string中
  8. python如何统计累计每日的人数‘’_Python数据分析2019陕西高考(理工)成绩及填报志愿...
  9. MongoDB 复制集和分片的理解
  10. Source Insight 3.5 序列号分享
  11. 计算机科学导论第五版第二章答案,《计算机科学导论》课后习题答案
  12. 程序员面试宝典——第6章
  13. 计算机实验室安全知识心得体会,实验室安全知识宣传
  14. pcb板led正负极图形_晶体二极管正负极判断_晶体二极管图形符号
  15. python中property详解
  16. HTML5期末大作业:个人网站设计——简单响应式个人博客HTML模板(8页面) HTML+CSS+JavaScript...
  17. 运行tomcat 时报错,提示无法找到相关的jar包 Publishing failed with multiple errors Error reading file
  18. 任务三、学生喂养三种宠物:猫、狗和鸟
  19. 良心安利秋分海报设计模板素材
  20. linux 建树软件,新一代建树工具IQ-Tree介绍

热门文章

  1. 从零开始学习 pycharm 注册8月3日
  2. 程序员如何选择macbookpro以及新macbookpro开箱
  3. java 测试带宽_使用Speedtest CLI测试你的网速
  4. 计算机体系结构-体系结构基础与流水线原理
  5. java识别不了欧元 符号_java – 使用unicode显示欧元符号并将字符更改为大写
  6. emq的客户端与服务端_使用 EMQ X Cloud 物联网 MQTT 云服务
  7. 解决Android,ios字体设置font-weight后粗细显示效果不一问题
  8. python中matlab中xlabel数值_如何在matlab中的xlabel,ylabel,legend和text函数中使用latex...
  9. SpringCloud快速入门(基于狂神讲解)
  10. vscode真的不太好用!