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函数来提供引用计数功能。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
/*** 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基类,以便具有引用计数功能。
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
#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,即使不需要,引用计数成员也会被创建。
boost::intrusive_ptr原理介绍的更多相关文章
- 03 Yarn 原理介绍
Yarn 原理介绍 大纲: Hadoop 架构介绍 YARN 产生的背景 YARN 基础架构及原理 Hadoop的1.X架构的介绍 在1.x中的NameNodes只可能有一个,虽然可以通过Se ...
- 04 MapReduce原理介绍
大数据实战(上) # MapReduce原理介绍 大纲: * Mapreduce介绍 * MapReduce2运行原理 * shuffle及排序 定义 * Mapreduce 最早是由googl ...
- Android Animation学习(一) Property Animation原理介绍和API简介
Android Animation学习(一) Property Animation介绍 Android Animation Android framework提供了两种动画系统: property a ...
- [转]MySQL主从复制原理介绍
MySQL主从复制原理介绍 一.复制的原理 MySQL 复制基于主服务器在二进制日志中跟踪所有对数据库的更改(更新.删除等等).每个从服务器从主服务器接收主服务器已经记录到其二进制日志的保存的更新,以 ...
- 分布式文件系统FastDFS原理介绍
在生产中我们一般希望文件系统能帮我们解决以下问题,如:1.超大数据存储:2.数据高可用(冗余备份):3.读/写高性能:4.海量数据计算.最好还得支持多平台多语言,支持高并发. 由于单台服务器无法满足以 ...
- 内存分析_.Net内存原理介绍
内存原理介绍 1. .Net应用程序中的内存 1.1.Net内存类型 Windows使用一个系统:虚拟寻址系统.这个系统的作用是将程序可用的内存地址映射到硬件内存中的实际地址上.其实际结果 ...
- 液晶常用接口“LVDS、TTL、RSDS、TMDS”技术原理介绍
液晶常用接口“LVDS.TTL.RSDS.TMDS”技术原理介绍 1:Lvds Low-Voltage Differential Signaling 低压差分信号 1994年由美国国家半导体公司提出之 ...
- 淘宝JAVA中间件Diamond详解(2)-原理介绍
淘宝JAVA中间件Diamond详解(二)---原理介绍 大家好,通过第一篇的快速使用,大家已经对diamond有了一个基本的了解.本次为大家带来的是diamond核心原理的介绍,主要包括server ...
- Traceroute原理介绍
一.路由追踪 路由跟踪,就是获取从主机A到达目标主机B这个过程中所有需要经过的路由设备的转发接口IP. 二.ICMP协议 Internet控制报文协议(internet control message ...
随机推荐
- Cloudera Manager集群官方默认的各个组件开启默认顺序(图文详解)
不多说,直接上干货! 如下是 Cloudera Manager集群官方默认的各个组件开启默认顺序. http://192.168.80.31:7180/cmf/clusters/1/express-a ...
- mvc框架的学习步骤
1 搭建环境.有个感性认识 2 如何完成controller和viewer的映射 3 如何把值传给controller 4 controller如何把值传给view 5 异常处理 6 页面标签 7文件 ...
- Maven 常见知识点整理
认识 Maven Maven 的作用? 1.添加第三方jar包 2.解决jar包之间的依赖关系 3.获取第三方jar包 4.将项目拆成多个工程模块 Maven 是什么? 是Apache软件基金会组织维 ...
- [LNMP]——LNMP环境配置
LNMP=Linux+Nginx+Mysql+PHP Install Nginx //安装依赖包 # yum install openssl openssl-devel zlib-devel //安装 ...
- sed常用命令
sed也是一个管道命令. sed [-nefr] [动作] -n 加上-n参数后,只有经过sed特殊处理的那些行才会被列出来 -e 直接在命令行模式进行sed的动作编辑 -i 直接修改读取的文件内容 ...
- HTTP中的响应协议及302、304的含义
响应协议 HTTP/1.1 200 OK:响应协议为HTTP1.1,状态码为200,表示请求成功,OK是对状态码的解释: Server: Apache-Coyote/1.1:服务器的版本信息: Con ...
- [javaEE] 三层架构案例-用户模块(二)
使用junit测试框架,测试查找用户和添加用户功能 com.tsh.test.xmlUserDaoTest package com.tsh.test; import org.junit.Test; i ...
- The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the associated filter.
The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the assoc ...
- Java数组逆序存储
package review01; import java.util.Arrays; public class review01 { public static void main(String[] ...
- Spring学习笔记:Spring动态组装打印机
一.如何开发一个打印机 1.可灵活配置使用彩色魔盒或灰色魔盒 2.可灵活配置打印页面的大小 二.打印机功能的实现依赖于魔盒和纸张 三.步骤: 1.定义墨盒和纸张的接口标准 package cn.pri ...