boost::intrusive_ptr原理介绍

boost::intrusive_ptr一种“侵入式”的引用计数指针,它实际并不提供引用计数功能,而是要求被存储的对象自己实现引用计数功能,并提供intrusive_ptr_add_refintrusive_ptr_release函数接口供boost::intrusive_ptr调用。

下面通过一个具体的例子来说明boost::intrusive_ptr的用法,首先实现一个基类intrusive_ptr_base,定义intrusive_ptr_add_ref和intrusive_ptr_release函数来提供引用计数功能。

01/**
02* intrusive_ptr_base基类,提供intrusive_ptr_add_ref()和intrusive_ptr_release()函数来提供引用计数功能;
03* 使用boost::intrusive_ptr指针存储的用户类类型必须继承自intrusive_ptr_base基类。
04*/
05#include <ostream>
06#include <boost/checked_delete.hpp>
07#include <boost/detail/atomic_count.hpp>
08  
09  
10template<class T>
11class intrusive_ptr_base {
12public:
13    /**
14    * 缺省构造函数
15    */
16    intrusive_ptr_base(): ref_count(0) {
17        std::cout << "  Default constructor " << std::endl;
18    }
19      
20    /**
21    * 不允许拷贝构造,只能使用intrusive_ptr来构造另一个intrusive_ptr
22    */
23    intrusive_ptr_base(intrusive_ptr_base<T> const&): ref_count(0) {
24        std::cout << "  Copy constructor..." << std::endl;
25    }
26      
27    /**
28    * 不允许进行赋值操作
29    */
30    intrusive_ptr_base& operator=(intrusive_ptr_base const& rhs) {
31        std::cout << "  Assignment operator..." << std::endl;
32        return *this;
33    }
34      
35    /**
36    * 递增引用计数(放到基类中以便compiler能找到,否则需要放到boost名字空间中)
37    */
38    friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s) {
39        std::cout << "  intrusive_ptr_add_ref..." << std::endl;
40        assert(s->ref_count >= 0);
41        assert(s != 0);
42        ++s->ref_count;
43    }
44  
45    /**
46    * 递减引用计数
47    */
48    friend void intrusive_ptr_release(intrusive_ptr_base<T> const* s) {
49        std::cout << "  intrusive_ptr_release..." << std::endl;
50        assert(s->ref_count > 0);
51        assert(s != 0);
52        if (--s->ref_count == 0)
53            boost::checked_delete(static_cast<T const*>(s));  //s的实际类型就是T,intrusive_ptr_base<T>为基类
54    }
55      
56    /**
57    * 类似于shared_from_this()函数
58    */
59    boost::intrusive_ptr<T> self() {
60        return boost::intrusive_ptr<T>((T*)this);
61    }
62      
63    boost::intrusive_ptr<const T> self() const {
64        return boost::intrusive_ptr<const T>((T const*)this);
65    }
66      
67    int refcount() const {
68        return ref_count;
69    }
70      
71private:
72    ///should be modifiable even from const intrusive_ptr objects
73    mutable boost::detail::atomic_count ref_count;
74  
75};

用户类类型需要继承intrusive_ptr_base基类,以便具有引用计数功能。

01#include <iostream>
02#include <string>
03#include <boost/intrusive_ptr.hpp>
04#include "intrusive_ptr_base.hpp"
05  
06/**
07* 用户类类型继承自intrusive_ptr_base,该实现方式类似于boost::enable_shared_from_this<Y>
08*/
09class Connection : public intrusive_ptr_base< Connection > {
10public:
11    /**
12    * 构造函数,调用intrusive_ptr_base< Connection >的缺省构造函数来初始化对象的基类部分
13    */
14    Connection(int id, std::string tag):
15        connection_id( id ), connection_tag( tag ) {}
16  
17    /**
18    * 拷贝构造函数,只复制自身数据,不能复制引用计数部分
19    */
20    Connection(const Connection& rhs):
21        connection_id( rhs.connection_id ), connection_tag( rhs.connection_tag) {}
22      
23    /**
24    * 赋值操作,同样不能复制引用计数部分
25    */
26    const Connection operator=( const Connection& rhs) {
27        if (this != &rhs) {
28            connection_id = rhs.connection_id;
29            connection_tag = rhs.connection_tag;
30        }
31          
32        return *this;
33    }
34  
35private:
36    int connection_id;
37    std::string connection_tag;
38};
39  
40int main() {
41    std::cout << "Create an intrusive ptr" << std::endl;
42    boost::intrusive_ptr< Connection > con0 (new Connection(4, "sss") );  //调用intrusive_ptr_add_ref()递增引用计数
43    std::cout << "Create an intrusive ptr. Refcount = " << con0->refcount() << std::endl;
44  
45    boost::intrusive_ptr< Connection > con1 (con0);   //调用intrusive_ptr_add_ref()
46    std::cout << "Create an intrusive ptr. Refcount = " << con1->refcount() << std::endl;
47    boost::intrusive_ptr< Connection > con2 = con0;   //调用intrusive_ptr_add_ref()
48    std::cout << "Create an intrusive ptr. Refcount = " << con2->refcount() << std::endl;
49      
50    std::cout << "Destroy an intrusive ptr" << std::endl;
51  
52    return 0;
53}

程序运行输出:

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析构时。即不能如下使用:

  int *a = new int(5);
  boost::shared_ptr ptr1(a);
  boost::shared_ptr ptr2(a);  //错误! 
 
boost::intrusive_ptr完全具备boost::shared_ptr的功能,且不存在shared_ptr的问题,即可以利用raw pointer创建多个intrusive _ptr,其原因就在于引用计数的 ref_count对象,shared_ptr是放在 shared_ptr结构里, 而目标对象T通过继承 intrusive_ptr_base将引用计数作为T对象的内部成员变量,就不会出现同一个对象有两个引用计数器的情况出现。
 

 

那么为什么通常鼓励大家使用shared_ptr,而不是intrusive_ptr呢, 在于shared_ptr不是侵入性的,可以指向任意类型的对象; 而intrusive_ptr所要指向的对象,需要继承intrusive_ptr_base,即使不需要,引用计数成员也会被创建。

  

结论:如果创建新类且需要进行传递,则 继承 intrusive_ptr_base,使用intrusive_ptr。
 
 

原文地址:

boost intrusive_ptr原理(兼对比shared_ptr)

boost intrusive_ptr

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值