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 ...
随机推荐
- java获取当前秒数输出
Date的getSeconds()已经过时了.不建议用.所以用了下面方法 Calendar c = Calendar.getInstance(); while(true) { c ...
- Mongodb cassandra 和 Mysql对比
MongoDBDB.Cassandra和 Mysql对比 1.为什么是Nosql? 1.1 Nosql在大数据处理相对于关系型数据库具有优势 1.1.1 1. 低延迟 ...
- oracle系统包——dbms_alert用法
oracle内部提供的在数据库内部和应用程序间通信的方式有以下几种:1.警报,就是DBMS_ALERT包提供的功能:2.管道,由DBMS_PIPE提供:3.高级队列,这个就很复杂,当然提供的功能也是很 ...
- 微信小程序-tab标签栏实现教程
一.摘要 tab栏(标签切换栏)是app中常见的一种交互方式,它可以承载更多的内容,同时又兼顾友好体验的优点.但在小程序中,官方并没有为咱们提供现成的组件.因此我们程序员展现才艺的时候到了(其实市面上 ...
- 【c++】访问控制
1. 类内的访问控制 在基类中,public和private具有普通的含义:用户(即基类的对象)可以访问public成员(包括函数.数据),而不能访问private成员.private只能被基类的成 ...
- BNU 33693——Problemsetting——————【枚举+最大流】
Problemsetting Time Limit: 5000ms Memory Limit: 131072KB 64-bit integer IO format: %lld Java cl ...
- SSRS 通过Customer Code访问Dataset
A dataset in Reporting Services is not the same type of object as an ADO.Net dataset. A report data ...
- Tool Scripts
1. Function: 16进制转字符串 Create FUNCTION [dbo].[f_hextostr] (@hexstring VARCHAR(max)) RETURNS VARCHAR(m ...
- Redis单机数据迁移至Sentinel集群
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...
- python logging的应用
#-*-coding:utf-8-*-#util import logging import logging from logging.handlers import RotatingFileHand ...