Boost开发指南-3.7intrusive_ptr

news2024/11/24 20:48:38

intrusive_ptr

intrusive_ptr也是一种引用计数型智能指针,但与之前介绍的 scoped_ptr,shared_ptr 不同,需要额外增加一些的代码才能使用。它的名字可能会给人造成误解,实际上它并不一定要修改代理对象的内部数据。

如果现存代码已经有了引用计数机制管理的对象,那么 intrusive_ptr 是一个非常好的选择,可以包装已有对象从而得到与shared_ptr类似的智能指针。

类摘要

template<class T>
class intrusive_ptr 
{
public:
   typedef T element_type; //被代理的对象
   intrusive_ptro(); //构造函数
   intrusive_ptr(T * p, bool add_ref = true);
   intrusive_ptr(intrusive_ptr const & r);
   template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
   
   ~intrusive_ptr():
  
   intrusive_ptr & operator=(intrusive_ptr const &r);
   template<class Y> intrusive_ptr & operator=(intrusive_ptr<Y> const & r);
   intrusive_ptr & operator=(T * r);
  
   void reset(); //重置指针
   void reset(T * r);
   void reset(T * r, bool add_ref);
   
   T & operator*() const; //操作符重载
   T * operator->() const;
   explicit operator bool() const;
   
   T* get() const;
   T * detach();
   void swap(intrusive__ptr & b);
};

因为intrusive_ptr也是引用计数型指针,所以它的接口与shared_ptr很像,也同样支持比较和static_pointer_cast ()、dynamic_pointer_cast()等转型操作,但它自己不直接管理引用计数,而是调用下面两个函数来间接管理:

void intrusive_ptr_add_ref(T * p); //增加引用计数
void intrusive_ptr_release(T * p); //减少引用计数

intrusive_ptr的构造函数和reset()还多出一个add_ref参数,表示是否增加引用计数,如果add_refm=true,那么它就相当于weak_ptr,只是简单地观察对象。

用法

假设我们已经有了一个自己实现引用计数的类counted_data:

struct counted_data //自己实现引用计数
{
	int m_count = 0; //引用计数
	... //其他数据类型
};

为了让intrusive_ptr能够管理counted_data,我们需要实现它要求的两个回调函数:

void intrusive_ptr_add_ref(counted_data* p) //增加引用计数
{
	++p->m_count;
}

void intrusive_ptr_release(counted_data* p) //减少引用计数
{
	if (--p->m_count == 0)
	{
		delete p; //引用计数为0 则删除指针
	}
}

注意:在 intrusive_ptr_release()函数里必须检查引用计数,因为intrusive_ptr不负责实例的销毁,这个工作必须由我们自己完成。

实现intrusive_ptr_release()和intrusive_ptr_release()后intrusive_ptr就可以管理counted_data了,示范代码如下:

int main()
{
	typedef intrusive_ptr<counted_data> counted_ptr; //类型定义

	counted_ptr p(new counted_data); //创建智能指针
	assert(p); //bool转型
	assert(p->m_count == 1); //operator->

	counted_ptr p2(p); //指针拷贝构造
	assert(p->m_count == 2); //引用计数增加

	counted_ptr weak_p(p.get(), false); //弱引用
	assert(weak_p->m_count == 2); //引用计数不增加

	p2.reset(); //复位指针
	assert(!p2); //p2不持有指针
	assert(p->m_count == 1); //引用计数不增加

} //对象被正确析构

可以看到,只需要编写少量的代码,我们就可以复用既存的数据结构,获得一个与shared_ptr 用法几乎一样的智能指针,而且并没有增加多余的开销,这在某些对性能要求比较苛刻的场景里非常有用。

但大多数情况下shared_ptr 完全不必增加新代码,而且提供了更多的灵活性,使用intrusive_ptr前必须要确定它能够带来足够多的好处。

引用计数器

为了简化实现引用计数的工作, intrusive_ptr在头文件<boost/smart_ptr/intrusive_ref_counter.hpp>里定义了一个辅助类intrusive_ref_counter,声明如下:

template<typename DerivedT,
         typename CounterPolicyT = thread_safe_counter>
class intrusive_ref_counter
private:
   typedef typenamie counterPolicyT::type counter_type;
   mutable counter_type m_ref_counter;
public:
   intrusive_ref_counter();
   unsigned int use_count() const;
protected:
   ~intrusive_ref_counter() = default;
   friend void intrusive_ptr_add_ref(const intrusive_ref_counter* p);
   friend void intrusive_ptr_release(const intrusive_ref_counter* p);
);

intrusive_ref_counter内部定了一个计数器变量m_ref_counter,使用模板参数CounterPolicyT配置策略类实现了计数的增减,缺省的策略是线程安全的thread_safe_counter。

intrusive_ref_counter需要被继承使用,这样子类就会自动获得引用计数的能力,之前的counted_data可以简化如下:

struct counted_data2 : public intrusive_ref_counter<counted_data2>
{
	...
};

int main()
{
	typedef intrusive_ptr<counted_data2> counted_ptr; //类型定义

	counted_ptr p(new counted_data2); //创建智能指针
	assert(p); //bool转型
	assert(p->use_count() == 1); //operator->
} //对象被正确析构

代码示例

#include <iostream>
using namespace std;

#include <boost/smart_ptr.hpp>
using namespace boost;

//

struct counted_data
{
	// ...
	int m_count = 0;
	~counted_data()
	{
		cout << "dtor" << endl;
	}
};

void intrusive_ptr_add_ref(counted_data* p)
{
	++p->m_count;
}

void intrusive_ptr_release(counted_data* p)
{
	if (--p->m_count == 0)
	{
		delete p;
	}
}

//
#include <boost/smart_ptr/intrusive_ref_counter.hpp>

struct counted_data2 : public intrusive_ref_counter<counted_data2>
{
	~counted_data2()
	{
		cout << "dtor2" << endl;
	}
};
//

int main()
{
	typedef intrusive_ptr<counted_data> counted_ptr;

	counted_ptr p(new counted_data);
	assert(p);
	assert(p->m_count == 1);

	counted_ptr p2(p);
	assert(p->m_count == 2);

	counted_ptr weak_p(p.get(), false);
	assert(weak_p->m_count == 2);

	p2.reset();
	assert(!p2);
	assert(p->m_count == 1);

	{
		typedef intrusive_ptr<counted_data2> counted_ptr;

		counted_ptr p(new counted_data2);
		assert(p);
		assert(p->use_count() == 1);

	}
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/820005.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一个月,英语能提高多少?附资料分享

学习语言是一个漫长的过程&#xff0c;但对于我这样一个英语小白&#xff0c;利用业余时间&#xff0c;一个月的学习&#xff0c;还是能看到不少的进步。除了听、说、读、写等能力方面有提升之外&#xff0c;最大的收获就是培养了英语学习和运用的兴趣。这样的结果对我来说&…

《Python深度学习-Keras》精华笔记1:深度学习数学基础及张量

公众号&#xff1a;尤而小屋作者&#xff1a;Peter编辑&#xff1a;Peter 持续更新《Python深度学习》一书的精华内容&#xff0c;仅作为学习笔记分享。 本文是第一篇&#xff1a;深度学习中的数学基础和张量操作 In [1]: import pandas as pd import numpy as npimport tens…

【linux--->传输层协议】

文章目录 [TOC](文章目录) 一、端口号1.端口号划分范围2.常用知名端口号 二、网络命令1.netstat 命令2.pidof 命令 三、UDP协议1.格式2.协议的分离和合并3.特点4.缓冲区 四、TCP协议1.格式2.4位的数据偏移3.确认应答机制4.序号与确认序号5.16位窗口6.标志位7.超时重传8.三次握手…

腾讯云TencentOS Server镜像系统常见问题解答

腾讯云TencentOS Server镜像是腾讯云推出的Linux操作系统&#xff0c;完全兼容CentOS生态和操作方式&#xff0c;TencentOS Server操作系统为云上运行的应用程序提供稳定、安全和高性能的执行环境&#xff0c;TencentOS可以运行在腾讯云CVM全规格实例上&#xff0c;包括黑石物理…

2023-07-31力扣每日一题

链接&#xff1a; 143. 重排链表 题意&#xff1a; 将链表L0 → L1 → … → Ln - 1 → Ln变成L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → … 解&#xff1a; 线性表法还是好写的 这边搞一下翻转法&#xff0c;快慢指针求翻转点&#xff08;翻转后面一半然后双指针合并…

【运维】linkis1.3.2版本保姆级安装

文章目录 一.建议配置1 软硬件环境建议配置1.1 Linux 操作系统版本要求1.2 服务器建议配置1.3 软件要求1.4 客户端 Web 浏览器要求2.3 LDAP设置&#xff08;暂时不需要&#xff09; 二. 下载三. 安装部署linkis server端1. 首次安装准备事项1.1 Linux服务器1.2 添加部署用户 2.…

《入门级-Cocos2dx4.0 塔防游戏开发》---第四课:欢迎界面开发(二)

目录 一、开发环境介绍 二、开发内容 2.1. logo变化动画 2.2. logo帧动画 2.3 start按钮移动动画 2.4 Credite移动动画 三、显示效果 四、知识总结 1. 移动动画 2. 变大变小动画 3. 延时效果 4. 动画组 一、开发环境介绍 操作系统&#xff1a;UOS1060专业版本。 c…

Java常用API:Math、Syetem、Runtime、BigDecimal

Math类 //目标:了解下Nath类提供的常见方法。 // 1、public static int abs(int a):取绝对值&#xff08;拿到的结果一定是正数&#xff09; //public static double abs(double a) system.out.println(Math.abs(-12)); // 12 system.out.println(Math.abs(123));// 123 system…

upload-labs靶场全通关

upload-labs靶场全通关 pass-1pass-2pass-3pass-4pass-5pass-6pass-7pass-8pass-9pass-10pass-11pass-12pass-13pass-14pass-15pass-16pass-17pass-18pass-19pass-20 pass-1 首先我们新建一个php的webshell文件 在这里我写了一个rabb1t.php的shell文件 内容为这个样子 然后我…

【LeetCode经典算法】链表反转

题目 题目&#xff1a;给定单链表头节点&#xff0c;将单链表的链接顺序反转过来 例&#xff1a; 输入&#xff1a;1->2->3->4->5 输出&#xff1a;5->4->3->2->1 要求&#xff1a;按照两种方式实现 解决办法 方式一&#xff1a; 思路 单链表的结…

DH算法、DHE算法、ECDHE算法演进

ECDHE 算法解决了 RSA 算法不具备前向安全的性质 和 DH 算法效率低下的问题。 ECDHE 算法具有前向安全。所以被广泛使用。 由什么演变而来 DH 算法 -- > DHE 算法 -- > ECDHE 算法 DH 算法是非对称加密算法&#xff0c;该算法的核心数学思想是离散对数。 核心数学思…

wms-3代货架标签(电池版本)接口文档

一、查询标签信息接口 接口类型&#xff1a;POST, 参数格式&#xff1a;json array 链接形式&#xff1a; http://localhost/wms/associate/getTagsMsg 代码形式&#xff1a; { url : http://localhost/wms/associate/getTagsMsg, requestMethed : GET, requestParamet…

亚马逊买家账号ip关联怎么处理

对于亚马逊买家账号&#xff0c;同样需要注意IP关联问题。在亚马逊的眼中&#xff0c;如果多个买家账号共享相同的IP地址&#xff0c;可能会被视为潜在的操纵、违规或滥用行为。这种情况可能导致账号受到限制或处罚。 处理亚马逊买家账号IP关联问题&#xff0c;建议采取以下步骤…

有哪些很奇PA,但又比较少人知道的病毒?

世界上有哪些很奇PA&#xff08;或者说很搞笑&#xff09;&#xff0c;但又比较少人知道的病毒&#xff1f; ①温州皮鞋厂病毒 中毒迹象&#xff1a;播放出我们熟悉的《温州皮鞋厂倒闭了》bgm&#xff0c;并出现“捍卫版权&#xff0c;盗&#xff08;到&#xff09;此为止”…

DAY15_VUEElement综合案例

目录 1 VUE1.1 概述1.1.1 Vue js文件下载 1.2 快速入门1.3 Vue 指令1.3.1 v-bind & v-model 指令1.3.2 v-on 指令1.3.3 条件判断指令1.3.4 v-for 指令 1.4 生命周期1.5 案例1.5.1 需求1.5.2 查询所有功能1.5.3 添加功能 2 Element2.0 element-ui js和css和字体图标下载2.1 …

C++ 类和对象篇(二) this指针

目录 一、this指针概念 二、this指针的特性 三、this指针存在哪里&#xff1f; 四、this指针可以为空吗&#xff1f; 一、this指针概念 1.是什么&#xff1f; 它是类内非静态成员函数的隐含形参&#xff0c;this指针指向调用该函数的对象。 this指针是C编译器给每个“非静态…

适应于Linux系统的三种安装包格式 .tar.gz、.deb、rpm

deb、rpm、tar.gz三种Linux软件包的区别 rpm包-在红帽LINUX、SUSE、Fedora可以直接进行安装&#xff0c;但在Ubuntu中却无法识别&#xff1b; deb包-是Ubuntu的专利&#xff0c;在Ubuntu中双击deb包就可以进入自动安装进程&#xff1b; tar.gz包-在所有的Linux版本中都能使用…

【100天精通python】Day21:文件及目录操作_文件的权限处理和批量处理

目录 专栏导读 1. 文件的权限处理 1.1 查询文件权限 1.2 修改文件权限 2 文件的批量处理 2.1 使用os模块和os.listdir()函数 2.2 使用glob模块 2.3 使用shutil模块 2.3.1 批量复制文件 2.3.2 批量移动文件 2.3.3 批量删除文件 2.3.4 批量创建目录 专栏导读 专栏订阅…

Python程序开发案例教程PDF,python程序开发案例教程

大家好&#xff0c;本文将围绕Python程序开发案例教程黑马程序员电子版书展开说明&#xff0c;Python程序开发案例教程黑马课后答案是一个很多人都想弄明白的事情&#xff0c;想搞清楚Python程序开发案例教程pdf黑马程序员需要先了解以下几个事情。 1、python软件开发的案例有哪…

多赛道出海案例,亚马逊云科技为企业提供全新解决方案实现高速增长

数字化浪潮之下&#xff0c;中国企业的全球化步伐明显提速。从“借帆出海”到“生而全球化”&#xff0c;中国企业实现了从低端制造出口&#xff0c;向技术创新和品牌先导的升级。为助力中国企业业务高效出海&#xff0c;亚马逊云科技于2023年6月9日在深圳大中华喜来登酒店举办…