enable_shared_from_this 实现原理

前言

enable_shared_from_this 可以帮助我们用 this 指针安全地创建 shared_ptr。

enable_shared_from_this

假设我们的程序使用 shared_ptr 管理 Widget 对象,我们用一个 vector 来记录已经处理过的 Widget 对象:

std::vector<std::shared_ptr<Widget>> processedWidgets;

继续,假设 Widget 有一个用于处理的成员函数:

class Widget {public:void process() {// 处理 Widget// 然后将它添加到已处理过的 Widget 列表中processedWidgets.emplace_back(this);}
};

上面的代码可以通过编译,但是向 shared_ptr 的容器传递一个原始指针(this),shared_ptr 会由此为指向的 Widget 创建一个控制块(使用原始指针创建 shared_ptr 时会创建一个控制块来控制资源的释放)。

听起来没什么问题,直到你意识到如果成员函数外面早已存在指向那个 Widget 对象的指针,这时有多个控制块控制同一个资源,会导致资源重复释放。

shared_ptr API 中早已有处理这种情况的设施。它就是 enable_shared_from_this。如果你想创建一个用 shared_ptr 管理的类,这个类能够用 this 指针安全的创建一个 shared_ptr,enable_shared_from_this 就可作为基类的模板类。

class Widget: public std::enable_shared_from_this<Widget> {public:void process() {processedWidgets.emplace_back(shared_from_this());}
};

继承 enable_shared_from_this 后,如果想从 this 指针创建一个 shared_ptr,只需要调用 shared_from_this() 函数即可。

实现原理

enable_shared_from_this 的源码如下:

template <class _Tp>
class enable_shared_from_this {mutable weak_ptr<_Tp> __weak_this_;
protected:enable_shared_from_this() {}~enable_shared_from_this() {}
public:shared_ptr<_Tp> shared_from_this() {return shared_ptr<_Tp>(__weak_this_);}shared_ptr<_Tp const> shared_from_this() const {return shared_ptr<const _Tp>(__weak_this_);}template <class _Up> friend class shared_ptr;
};

enable_shared_from_this 的代码看起来平平无奇,内部有一个成员 __weak_this_,当调用 shared_from_this() 时就根据这个 weak_ptr 创建一个 shared_ptr。

那是怎么用 weak_ptr 创建 shared_ptr 的,这个 __weak_this_ 又是什么时候初始化的呢,我们可以在 shared_ptr 的构造函数中找到答案。

template <class _Tp>
class shared_ptr {public:using element_type = _Tp;private:element_type*        __ptr_;__shared_weak_count* __cntrl_;public:template<class _Yp>shared_ptr(_Yp* __p): __ptr_(__p) {__cntrl_ = new __shared_weak_count();__enable_weak_this(__p);}template<class _Yp>shared_ptr(const weak_ptr<_Yp>& __r): __ptr_(__r.__ptr_),__cntrl_(__r.__cntrl_ ? __r.__cntrl_->lock() : __r.__cntrl_) {if (__cntrl_ == 0) {assert(!"bad_weak_ptr");}}private:template <class _Yp>void __enable_weak_this(const enable_shared_from_this<_Yp>* __e)  {if (__e) {// __e 是 Widget 类型的指针,this 是 shared_ptr<Widget> 类型的// 初始化它内部的 weak_ptr,以便后面根据指向的控制块创建 shared_ptr__e->__weak_this_ = *this;}}
};

在 shared_ptr(_Yp* __p) 中会调用 __enable_weak_this 将 enable_shared_from_this 中的 weak_ptr 赋值为当前 shared_ptr。

工作流程如下:

首先,我们的类(Widget)继承 enable_shared_from_this,此时 Widget 成员变量中多了一个 weak_ptr<Widget>,默认情况下该 weak_ptr 内部的指针都指向空。

然后,我们用 this 指针创建了一个 shared_ptr,在 shared_ptr 构造函数中,成员变量的 weak_ptr 指向刚创建的 shared_ptr。

于是当我们使用 shared_from_this() 时,会调用 shared_ptr(const weak_ptr<_Yp>& __r) 中,先将 ptr 指向 weak_ptr 指涉的资源,然后调用 __cntrl_->lock() 将控制块的引用计数加 1。

因此,如果我们想使用 shared_from_this(),必须已经存在一个指向当前对象的 shared_ptr。

参考资料

  • 《Effective Modern C++》
  • libcxx-3.5.0

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

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

相关文章

OSError: [WinError 1455] 页面文件太小,无法完成操作 的问题

实质问题是报错&#xff1a;caffe2_detectron_ops.dll“ or one of its dependencies 还需要安装一个包&#xff1a; pip install intel-openmp 安装之后顺利测试通过。

使用可接受gitlab参数的插件配置webhook

jenkins配置 安装Generic Webhook Trigger 配置远程触发令牌 勾选Print post content和Print contributed variables用于打印值 配置gitlab 选择新增webhook 配置webhook http://JENKINS_URL/generic-webhook-trigger/invoke,将JENKINS_URL修改成自己的jenkins地址 先保存…

【考研数学】准备开强化,更「张宇」还是「武忠祥」?

数一125学长前来回答&#xff0c;选择哪位老师的课程&#xff0c;这通常取决于你的个人偏好和学习风格&#xff01; 张宇老师和武忠祥老师都是非常有经验的数学老师&#xff0c;他们的教学方法各有特点。 张宇老师的教学风格通常被认为是通俗易懂&#xff0c;善于将复杂的概念…

【JS】基于原生JavaScript的大文件切片上传及断点续传实现

基于原生JavaScript的大文件切片上传及断点续传实现 在现代Web应用中,大文件上传是一个常见但具有挑战性的功能。随着文件大小的增加,如何高效可靠地上传文件至服务器成为亟待解决的问题。在本文中,我将介绍如何使用原生JavaScript实现大文件切片上传及断点续传功能。 为什…

嵌入式开发十四:按键输入实验

前面两个实验&#xff0c;我们介绍了 STM32F4 的 IO 口作为输出的使用&#xff0c;这一次&#xff0c;我们将向大家介绍如何使用 STM32F4 的 IO 口作为输入用。我们将利用板载的 4 个按键&#xff0c;来控制板载的两个 LED 的亮灭和蜂鸣器。通过本次的学习&#xff0c;你将了解…

C语言输出符

C语言输出符 以下是C语言中一些常用的格式化输出的格式控制符及其对应的数据类型&#xff1a; 格式控制符描述对应数据类型%d十进制有符号整数int%ld长整型long int%lld长长整型long long int%u十进制无符号整数unsigned int%lu无符号长整型unsigned long int%llu无符号长长整…

从独立开发者到成为SeaTunnel社区的贡献者,我做对了哪些事儿?

个人介绍 大家好&#xff0c;我是闫成雨&#xff0c;目前是一名独立开发者。专注于数据开发、机器学习、资源调度算法和分布式系统。 GitHub ID: CheneyYin 个人主页&#xff1a;https://cheneyyin.github.io/ 为社区做了哪些贡献 加强了Spark引擎和Flink引擎对SeaTunnel数据…

2024年最新软件测试面试题必问的1000题!

我了解的测试理论和方法包括以下几个方面&#xff1a; 黑盒测试与白盒测试&#xff1a; 黑盒测试&#xff1a;基于对软件系统外部行为进行测试&#xff0c;独立于内部代码实现细节。黑盒测试关注输入与输出之间的关系以及软件功能是否符合预期。白盒测试&#xff1a;基于对软件…

如何实现Linux双网卡同时连接内网和外网的配置?

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

Day29

回溯算法part03 LC39组合总和(未掌握) 未掌握分析&#xff1a;被数组中的元素可以被重复选取误导&#xff0c;同时没有想到暴力解法来理解回溯 暴力解法肯定是for循环遍历candidates中的每个元素&#xff0c;下一层子循环不像之前的组合题目那样从i1开始&#xff0c;该题目元…

Linux系统 的持续学习

昨天学习了目录结构、补充命令和配置网络&#xff0c;其中配置网络用了nat方法&#xff0c;今天学习用桥接方法&#xff0c;通配符、正则表达式的一部分内容。 桥接模式 如果重网卡失败&#xff1a; 1.检查配置文件是否正确 2.检查虚拟器编辑器有没有选对&#xff08;网卡类…

jiebaNET中文分词器

最近我接手了一个有趣的需求&#xff0c;需要对用户评价进行分词&#xff0c;进行词频统计和情绪分析&#xff0c;并且根据词频权重制成词云图以供后台数据统计&#xff0c;于是我便引入了jieba分词器,但是我发现网上关于jiebaNET相关文档实在太少了&#xff0c;甚至连配置文件…

弘君资本:降准降息利好哪些板块?

降准是指下降存款准备金率&#xff0c;降息是指下调存款利率&#xff0c;他们是一种宽松的货币政策&#xff0c;对股市来说是一种利好&#xff0c;其间利好以下板块&#xff1a; 1、券商板块 降准降息会影响投资渠道的扩宽&#xff0c;降低资金入市的机会成本&#xff0c;将更…

CyclicBarrier的 常用场景及使用示例

CyclicBarrier的 常用场景及使用示例 CyclicBarrier是Java并发编程中的另一种同步辅助工具&#xff0c;它用于控制多个线程相互等待&#xff0c;直到所有线程都到达一个共同的屏障点&#xff0c;然后所有线程才会继续执行。与CountDownLatch不同的是&#xff0c;CyclicBarrier…

python的转义序列和占位符

1.占位符 1.%s&#xff1a;用于插入字符串 name "Alice" message "Hello, %s!" % name print(message) # 输出&#xff1a;Hello, Alice!%d&#xff1a;用于插入整数 age 25 message "I am %d years old." % age print(message) # 输出…

chrome命令的使用

Chrome浏览器&#xff0c;也称为Google Chrome&#xff0c;是由Google公司开发的一款设计现代、快速且安全的网页浏览器。Chrome浏览器基于开源的Chromium项目&#xff0c;并增加了Google自己的一些独特功能。Chrome浏览器以其简洁的界面、快速的浏览速度和丰富的扩展程序而广受…

Linux 文本编辑相关指令、指令参数、使用例子

一些常见的Linux文本编辑和处理相关的指令&#xff0c;以及它们的参数和使用例子&#xff0c;以表格形式列出&#xff1a; 序号指令名称指令参数及说明指令使用例子及说明1cat-n: 显示每行的行号cat -n filename 显示文件内容及行号2less-i: 交互模式&#xff0c;允许搜索less…

付费解锁隐藏动力和续航,订阅制又被特斯拉玩出花了

我们知道&#xff0c;「订阅制」早已成互联网领域各路大厂玩烂的操作。 上到程序订阅付费使用&#xff08;例如 Offics、Adobe&#xff09;&#xff0c;下到各类功能服务订阅&#xff08;如影视会员、网盘会员等&#xff09;。 甚至于某东、某宝等网购平台也整出了 VIP 订阅服…

原地去重问题和合并有序数组问题

原地去重问题 给你一个 非严格递增排列 的数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使每个元素 只出现一次 &#xff0c;返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。这是leetcode上的一道题 这里我们用…

2024五月母亲节嘉年华活动方案

2024以花之名 致谢母亲簪花趣味亲子五月母亲节嘉年华活动方案-43P 活动策划信息&#xff1a; 方案页码&#xff1a;43页 文件格式&#xff1a;PPT 方案简介&#xff1a; 岁月温柔治愈 母爱闪闪发光 一年一度的PY圈孝子孝女大赛即将到来 本次母亲节&#xff0c;“以花之名…