llvm:: IntrusiveRefCntPtr
boost::intrusive_ptr
而intrusive_ptr
中的计数器是作为对象的数据成员存在的,并且intrusive_ptr
只是提供了增减计数器的接口。intrusive_ptr
中计数器与对象的示意图如下:
namespace boost {struct thread_unsafe_counter;struct thread_safe_counter;template<class DrivedT, class CounterPolicyT = thread_safe_counter>class intrusive_ref_counter{public:intrusive_ref_counter() = noexecpt;intrusive_ref_counter(intrusive_ref_counter *r) = noexcept;intrusive_ref_counter & operator=(intrusive_ref_counter const & r) noexcept;unsigned int use_count() const noexcept;protected:~intrusive_ref_counter() = default;};
}
The
intrusive_ptr
class template stores a pointer to an object with an embedded reference count. Every newintrusive_ptr
instance increments the reference count by using an unqualified call to the functionintrusive_ptr_add_ref
, passing it the pointer as an argument. Similarly, when anintrusive_ptr
is destroyed, it callsintrusive_ptr_release
; this function is responsible for destroying the object when its reference count drops to zero. The user is expected to provide suitable definitions of these two functions.
从上面的描述中我们得到如下几点信息:
intrusive_ptr
本质上存储的是一个指向对象的指针,其中这个对象“内嵌“了计数器- 每当
intrusive_ptr
由对象A创建时,就将对象A的计数加一 - 每当
intrusive_ptr
销毁时,其创建时对象的计数就减一,当计数减到0时,将该对象销毁 - 其中计数加一和减一的函数,
intrusive_ptr_add_ref()
和intrusive_ptr_release()
的实现由用户提供
instrusive_ptr
的声明大致如下:
namespace boost {template<class T> element_type;intrusive_ptr(); // never throwsintrusive_ptr(T *p, bool add_ref = true);intrusive_ptr(intrusive_ptr const & r)ltemplate<class Y> intrusive_ptr(intrusive_ptr<T> const &r);~intrusive_ptr();T & operator*() const;T *operator->() const;T *get() const;T *detach();
};
其中对于上述的构造函数和析构函数,细节如下:
intrusive_ptr(T * p, bool add_ref = true);
Effects:if (p != 0 && add_ref) intrusive_ptr_add_ref(p);
Postconditions:get() == p
intrusive_ptr(intrusive_ptr const & r);
template<class Y> intrusive_ptr(intrusive_ptr<Y> const & r);
Effects:if (r.get() != 0) intrusive_ptr_add_ref(r.get());
Postconditions:get() == r.get()
~intrusive_ptr();
Effects:if(get() != 0) intrusive_ptr_release(get())
另外对于intrusive_ptr_add_ref()
和intrusive_ptr_release()
,如果编译器支持ADL(Argument Dependent Lookup),就会在它们的参数所定义的namespace中查找二者的定义,否早它们必须定义在boost namespace中。
intrusive_ptr
vs std::shared_ptr
在intrusive_ptr class template中有如下两段描述,第一段描述使用intrusive_ptr
的主要原因,第二段说明在intrusive_ptr
和std::shared_ptr
相同的情况下,尽量使用std::shared_ptr
。
The main reasons to use
intrusive_ptr
are:
- Some existing frameworks or Oses provide objects with embedded reference counts;
- The memory footprint of
intrusive_ptr
is the same as the corresponding raw pointer;intrusive_ptr<T>
can be constructed from an arbitrary raw pointer of typeT*
.
As a general rule, if it isn’t obvious whether
intrusive_ptr
better fits your needs thanshared_ptr
, try ashared_ptr-
based design first.
对于第一段中第二个原因需要说明一下,为什么intrusive_ptr
占用的内存比shared_ptr
少,原因在于std::shared_ptr
理念上对象和计数的存放是分开的,所以大部分情况下每个std::shared_ptr
有两个指针的内存开销,一个指针指向control block(存储引用计数等信息),一个指针指向对象。之所以说大部分情况,是因为std::make_shared<>
会统一分配一整块内存存储计数和对象,此时就只需存储一个指针。
Memory footprint refers to the amount of main memory that a program uses or references while running. [Memory footprint]
std::shared_ptr
中的std::make_shared<>
前面提到了std::make_shared<>
会为计数和对象分配一整块内存,虽然标准中没有这样规定,但是由于std::make_shared
提供了这样的一个将计数和对象放在一起的机会,所以基本上所有的实现都会这样做。
std::shared_ptr<T>(new T(args…)) performs at least two allocations (one for the object T and one for the control block of the shared pointer), while std::make_shared<T> typically performs only one allocation (the standard recommends, but does not require this, all known implementations do this). [make_shared]
The storage is typically larger than sizeof(T) in order to use one allocation for both the control block of the shared pointer and the T object. The std::shared_ptr constructor called by this function enables shared_from_this with a pointer to the newly constructed object of type T. [make_shared]
std::make_shared
所带来的好处和坏处都是由这一个特点引发的,通常意义上使用std::make_shared
是好的,不仅包裹了内存的分配,不会将raw pointer暴露出来,避免了访问已释放内存的问题,同时也减少了内存的分配。stackoverflow上有一个相关的问题,见Difference in make_shared and normal shared_ptr in C++,比较详尽。
了解了std::make_shared
的好处以后,intrusive_ptr
的第三个优点也就显而易见了。使用一个raw pointer来构造std::shared_ptr
通常不能保证是安全的,反而更容易出错,因为raw pointer有可能在其他地方被使用,而std::shared_ptr
不能为这些使用增加计数或减少计数。而intrusive_ptr
就不会存在这个问题,因为raw pointer本身就存储有计数信息。
知乎上有一个intrusive_ptr
的问题,为什么 intrusive_ptr 没有进入标准库?,该问题下设提到了std::enable_shared_from_this
,由于我在工作中没有遇到很多使用std::enable_shared_from_this
的代码场景,理解不够深刻,所以先挖个坑。
llvm::IntrusiveRefCntPtr
待填
llvm:: IntrusiveRefCntPtr相关推荐
- 编译器 llvm clang 源码转换示例
编译器 llvm clang 源码转换示例 从git获取llvm项目的源码方式: git clone https://github.com/llvm/llvm-project.git 下载源码后,进入 ...
- LLVM与Clang编译图例
LLVM与Clang编译图例 参考链接: https://blog.csdn.net/u012874859/article/details/108530256
- 三段式LLVM编译器
三段式LLVM编译器 目录 概述 LLVM技术生态之编译器 一.传统编译器的设计 二.传统编译器模式的实现 三.LLVM的三段式实现 四.LLVM's Code Representation:LLVM ...
- LLVM Clang前端编译与调试
LLVM Clang前端编译与调试 iOS 关于编译 o 一.Objective-C 编译过程 o 为什么需要重新编译? o 编译步骤 o 二.编译步骤的详细说明 o 1.预处理 o 2.编译 o 词 ...
- LLVM与Clang局部架构与语法分析
LLVM与Clang局部架构与语法分析 Clang与LLVM LLVM整体架构,前端用的是clang,广义的LLVM是指整个LLVM架构,一般狭义的LLVM指的是LLVM后端(包含代码优化和目标代码生 ...
- LLVM语法语义指令特性
LLVM语法语义指令特性 High Level Structure Module Structure LLVM 程序由Module's组成,每个 's 是输入程序的一个翻译单元.每个模块由函数,全局变 ...
- CPU架构的llvm后端
Creating an LLVM Backend for the Cpu0 Architecture Backend structure • TargetMachine structure • Add ...
- LLVM编译器基础架构与DragonEgg示例
LLVM编译器基础架构与DragonEgg示例 LLVM 概述 LLVM 项目是模块化和可重用的编译器和工具链技术的集合.LLVM 与传统的虚拟机几乎没有关系."LLVM"这个名字 ...
- LLVM数据流分析的理论
LLVM数据流分析的理论 标量优化(scalar目录): 死代码消除(BDCE.cpp[code],ADCE.cpp[code],DCE.cpp[code]), 全局值编号(GVN.cpp[code] ...
最新文章
- 【Matlab】矩阵中选取任意子矩阵
- python源码文件_从源代码生成Python文件
- python委托模式详细解释
- sublime用cmd窗口调试python_Sublime Text设置程序输出窗口为dos窗口
- vue结合element实现自定义上传图片、文件
- windows/linuxjdk安装,jdk1.6升级到1.7
- linux操作命令之压缩命令
- 知识点收录04:MAVEN相关的知识点
- PIO(编程输入/输出模型)和DAM(直接访问内存)
- 鼠标上下滑轮时,来回乱跑
- 第四届“云鼎奖”网络投票火热进行中——入围名单一览
- day python calss08 深浅copy
- win10添加打印机--无法访问指定设备,路径或文件。。
- Oracle 重建TEMP表空间
- 小博老师解析Java核心技术 ——JDBC普通增删改操作
- telnet 访问80端口
- ZSTU OJ-4454 招兵买马
- 关于petitfatfs的移植问题
- springmvc之响应类型,string,void,ModelAndView
- React使用echarts-for-react
热门文章
- iec104点号_IEC104报文遥测信息提取方法与流程
- Amazon SageMaker Data Wrangler 简化数据准备过程,助力机器学习
- SKLearn 信用卡欺诈检测(creditcard)
- 曲线斜率与法向量综合辨析
- java多线程霓虹灯,Android 霓虹灯
- 计算机关闭更新配置win10,windows10取消自动更新怎么操作_win10怎样取消自动更新...
- 模运算(包含模的逆运算)
- 数据库中limit的 用法
- limit , 与 limit offset 的区别
- SpringBoot美化日志输出——自定义Banner艺术字体