通过源码抽丝剥茧理解enable_shared_form_this/shared_ptr/weak_ptr智能指针实现原理

源码解析

首先先看如下简单代码,我们通过代码的顺序逐步解析

#include <iostream>
#include <memory>
using namespace std;

class C :public enable_shared_from_this<C>{
public:
    C(){ std::cout<<"construct"<<endl; }
    ~C(){ cout<<"destruct"<<endl; }
    //C*object_ptr(){ return this; }
    shared_ptr<C> object_ptr(){
        return shared_from_this();
    }
};

int main() {
  shared_ptr<C> p1(new C);
  cout << p1.use_count() << endl;
  shared_ptr<C> p2(
      p1->object_ptr());
  cout << p2.use_count() << endl;
  return 0;
}

接下来,让我们随着程序代码一步步的抽丝剥茧,看清c++智能指针背后的实现原理

首先我们先看main函数第一句代码,这一行代码有两个关键,

  1. 奇异递归模板 基类enable_shared_from_this的构造
  2. shared_ptr的构造
shared_ptr<C> p1(new C);

首先,在new对象时候,先执行构造函数,由于enable_shared_from_this是基类,cpp在构造对象时候是自底向上,所以此时子类还未开始构造,enable_shared_from_this在此时啥也不干,执行默认构造,enable_shared_from_this有一个成员变量weak_ptr,weak_ptr也进行默认构造(指针都被初始化为nullptr)

image-20240623150549041

我们首先认识一下**weak_ptr/unique_ptr的成员变量内存布局树结构(weak_ptrunique_ptr的内存布局可以说是一样的,细节看如下)**

class enable_shared_from_this{
    mutable weak_ptr<_Tp>  _M_weak_this;
}
// weak_ptr是其基类__weak_ptr的包装类,所以我们直接看__weak_ptr
class __weak_ptr{
    // 其实是一个指针,指向被监视变量的地址
	element_type*	 _M_ptr;         // Contained pointer.
    // 这就是weak_ptr智能指针的引用计数
	__weak_count<_Lp>  _M_refcount;    // Reference counter.
    //__shared_count<_Lp>  _M_refcount;    // Reference counter.
};
class __shared_count{
    //如下是智能指针引用计数的成员变量指针,里面放着真正的引用计数数据
	_Sp_counted_base<_Lp>*  _M_pi;
};
class __weak_count{
    //如下是智能指针引用计数的成员变量指针,里面放着真正的引用计数数据
	_Sp_counted_base<_Lp>*  _M_pi;
};
class _Sp_counted_base{
    // 资源被shared_ptr持有数量
	_Atomic_word  _M_use_count;     // #shared
	// 资源被weak_ptr监视数量
    _Atomic_word  _M_weak_count;    // #weak + (#shared != 0)
}

此时对象已经构造完毕,new返回对象地址,进入unique_ptr的构造函数,在这里指向资源的_M_ptr和指向引用计数的_M_refcount被初始化

image-20240623152301321

如下图所示,此图是上图中_M_refcount指向引用计数指针初始化函数,

image-20240623153113331

还记得前面的enable_shared_from_this吗,在之前的对象构造初始化中,enable_shared_from_this被默认初始化,现在unique_ptr初始化完毕后在_M_enable_shared_from_this_with函数中会检测对象是否继承了enable_shared_from_this,如有,便在刺客进行真正的初始化

  1. __enable_shared_from_this_base():这里直接返回了指针
  2. _M_weak_assign():调用weak_ptr\_M_assign函数进行真正的初始化enable_shared_from_thisweak_ptr对象,

image-20240623153624491

image-20240623153724299

image-20240623154532042

如此,整个shared_ptr p1(new C);执行流程便是结束了.接下来调用cout << p1.use_count() << endl;此时由于只有一个输出1,

此时有一个unique_ptr在引用对象和enable_shared_from_this基类的weak_ptr在监视对象,所以use countweak count数量都是1,

image-20240623155304716

接下来我们再看调用shared_form_this构造一个shared_ptr会发生什么

可以看见,shared_form_this实际就是拿基类enable_shared_from_this所持有的weak_ptr去构建一个uniqe_ptr并返回

shared_ptr<_Tp> shared_from_this() {
    return shared_ptr<_Tp>(this->_M_weak_this);
}

接下来可以看见,此时是两个unique_ptr和一个weak_ptr

image-20240623160514744

内存布局图

画的一个简易的智能指针内存布局

image-20240623161149740

简单总结

使用std::make_shared与new的内存区别

使用new,资源的内存在堆上面,使用make_shared资源在STL空间配置器(内存池)中

enable_shared_from_this的实现原理

通过c++模板编程的奇异爹递归模板,基类持有一个派生类的weak_ptr,在shared_form_this函数中使用weak_ptr初始化一个unique_ptr返回给用户使用

shared_ptr与weak_ptr

一同指向资源的地址,引用计数在堆上面,二者指向同一份引用计数(通过原子变量保证引用计数的多线程安全性),引用计数为0时候销毁,但如果有weak_ptr在监视资源,会导致延迟销毁

tr`返回给用户使用

shared_ptr与weak_ptr

一同指向资源的地址,引用计数在堆上面,二者指向同一份引用计数(通过原子变量保证引用计数的多线程安全性),引用计数为0时候销毁,但如果有weak_ptr在监视资源,会导致延迟销毁

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mqtt介绍和环境安装

Mqtt介绍 MQTT是机器对机器(M2M)/物联网(IoT)连接协议。它被设计为一个极其轻量级的发布/订阅消息传输协议。对于需要较小代码占用空间和/或网络带宽非常宝贵的远程连接非常有用&#xff0c;是专为受限设备和低带宽、高延迟或不可靠的网络而设计。 下载一个开源的emqx服务器和…

ARM功耗管理软件之时钟电源树

安全之安全(security)博客目录导读 思考&#xff1a;功耗管理软件栈及示例&#xff1f;WFI&WFE&#xff1f;时钟&电源树&#xff1f;DVFS&AVS&#xff1f; 目录 一、时钟&电源树简介 二、时钟树示例 三、电源树示例 一、时钟&电源树简介 时钟门控与自…

iPhone苹果手机iOS18如何隐藏打开APP怎么找出来恢复隐藏APP?

iPhone苹果手机如何隐藏APP&#xff1f; 1、iPhone苹果手机上一些APP不想让别人看到可以设置为隐藏APP&#xff0c;请长按要设置隐藏的APP&#xff0c;选择需要面容ID&#xff1b; 2、然后再接着选择隐藏并需要面容ID&#xff0c;选择后手机桌面将不在显示该APP&#xff1b; i…

短剧挂载推广教程,短剧项目怎么分销推广?如何入驻平台当推广达人?达人推广的方式是怎么样的

目录 一、短剧怎么做&#xff1f; 二、在哪找资源挂?怎么挂? 1、在哪找资源挂? 2、怎么挂? 三、有哪些短剧看剧平台或者分销平台? 1&#xff1a;短剧看剧小程序怎么入驻当达人? 2&#xff1a;短剧cps分销小程序怎么入驻当达人? 一、短剧怎么做&#xff1f; 想要当…

[leetcode]minimum-absolute-difference-in-bst 二叉搜索树的最小绝对差

. - 力扣&#xff08;LeetCode&#xff09; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(null…

Meta低头,库克认错,XR回归第一性原理

图片&#xff5c;Photo by Maxim Hopman on Unsplash ©自象限原创 作者丨罗辑 2024年&#xff0c;XR的故事应该怎么讲&#xff1f; 如果从数据上看&#xff0c;这应该是个沉重的话题。 根据 IDC 报告&#xff0c;2023 年全球 VR 市场出货量下滑了 10.7%。2024 年第一…

安全为基、创新驱动,Soul App创始人张璐团队大力筑牢社交平台发展之基

随着技术的不断进步,AIGC在各个领域的应用日益广泛。在社交领域,AIGC社交为用户带来了更加高质量、个性化的社交体验,但同时也伴随着数据隐私泄露、网络诈骗和不良信息误导等风险。因此,社交平台在抓住AIGC技术发展机遇的同时,也要警惕技术所带来的风险。新型社交平台Soul App坚…

离线应用PWA-service work

1.有时候希望没有网络的时候,也可以正常的访问对应的页面,就需要用到service work 进行对应的配置,可以当页面的配置 也可以多页面的配置,单页面配置比较麻烦 就以uniapp框架为基础 来配置service work 一 配置 manifest 文件 (此manifest和uniapp 的 manifest.不是同…

网安小贴士(1)等级保护

一、定义 等保&#xff0c;即信息安全等级保护&#xff0c;根据信息系统在国家安全、经济建设、社会生活中的重要程度&#xff0c;以及信息系统遭到破坏后对国家安全、社会秩序、公共利益以及公民、法人和其他组织的合法权益的危害程度&#xff0c;将信息系统分为五个不同的安全…

[leetcode]文件组合

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:vector<vector<int>> fileCombination(int target) {vector<vector<int>> vec;vector<int> res;int sum 0, limit (target - 1) / 2; // (target - 1) / 2 等效于 target /…

《塔瑞斯世界》国服震撼登场!AOC助力玩家开启游戏新征途!

一款真正高画质、重机制、轻数值的MMORPG大作&#xff01; 你是否厌倦了在MMORPG游戏中被“氪金大佬”碾压&#xff1f;你是否渴望一个纯粹依靠技术和策略就能获得成就感的游戏世界&#xff1f;如果你对这两个问题的答案都是肯定的&#xff0c;那么《塔瑞斯世界》或许值得你一…

二叉树遍历练习题

2.已知某二叉树的前序遍历序列为5 7 4 9 6 2 1&#xff0c;中序遍历序列为4 7 5 6 9 1 2&#xff0c;则其后序遍历序列为&#xff08; &#xff09; A.4 2 5 7 6 9 1 B.4 2 7 5 6 9 1 C.4 7 6 1 2 9 5 D.4 7 2 9 5 6 1 答案&#xff1a;C 解析&#xff1a; 通过前序遍历找…

舞会无领导:一种树形动态规划的视角

没有上司的舞会 Ural 大学有 &#x1d441; 名职员&#xff0c;编号为1∼&#x1d441;。 他们的关系就像一棵以校长为根的树&#xff0c;父节点就是子节点的直接上司。 每个职员有一个快乐指数&#xff0c;用整数 &#x1d43b;&#x1d456; 给出&#xff0c;其中1≤&…

慧翰股份毛利率下滑:股权转让纠纷引关注,研发费用率远弱同行还买楼?

《港湾商业观察》施子夫 6月11日&#xff0c;慧翰微电子股份有限公司&#xff08;以下简称&#xff0c;慧翰股份&#xff09;IPO注册申请获证监会同意&#xff0c;预计公司将很快登陆深交所创业板&#xff0c;保荐机构为广发证券。 从业绩面来看&#xff0c;过去三年&#xf…

筛斗数据全面解析数据提取与清洗的重要性

筛斗数据全面解析数据提取与清洗的重要性 在数字化时代&#xff0c;数据是企业决策的重要依据。然而&#xff0c;数据并非总是以我们期望的形式出现&#xff0c;它们可能分散、冗余、错误甚至不完整。因此&#xff0c;数据提取与清洗成为数据处理流程中不可或缺的两个环节。筛…

ActiveMq工具之管理页面说明

文章目录 安装ActiveMQ一: 访问管理页面二: 进入管理页面&#xff0c;主页三: Queues页说明四: Topics页说明五: Subscribers页说明 安装ActiveMQ wget https://archive.apache.org/dist//activemq/5.13.3/apache-activemq-5.13.3-bin.tar.gz wget https://mirrors.huaweiclou…

docker-compose搭建minio对象存储服务器

docker-compose搭建minio对象存储服务器 最近想使用oss对象存储进行用户图片上传的管理&#xff0c;了解了一下例如aliyun或者腾讯云的oss对象存储服务&#xff0c;但是呢涉及到对象存储以及经费有限的缘故&#xff0c;决定自己手动搭建一个oss对象存储服务器&#xff1b; 首先…

[数据集][目标检测]城市街道井盖破损未盖丢失检测数据集VOC+YOLO格式4404张5类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;4404 标注数量(xml文件个数)&#xff1a;4404 标注数量(txt文件个数)&#xff1a;4404 标注…

嵌入式以太网硬件构成与MAC、PHY芯片功能介绍

一.以太网电路基本构成 1.总体介绍 对于上述三部分&#xff0c;并不一定都是独立的芯片&#xff0c;主要有以下几种情况&#xff1a; CPU内部集成了MAC和PHY&#xff0c;难度较高&#xff1b; CPU内部集成MAC,PHY采用独立芯片(主流方案)&#xff1b; CPU不集成MAC和PHY&#…

.net8 Syncfusion生成pdf/doc/xls/ppt最新版本

新建控制台程序 添加包Syncfusion.Pdf.Net.Core包&#xff0c;当前官方的版本号为26.1.39 直接上代码 Syncfusion.Pdf.PdfDocument pdfDocument new Syncfusion.Pdf.PdfDocument(); for (int i 1; i < 10; i) {var page pdfDocument.Pages.Add();PdfGraphics graphics…