当前位置: 首页 > news >正文

C++——shared_ptr:make_shared的用处,与shared_ptr直接构造的区别

shared_ptr

shared_ptr继承自__shared_ptr,其中有两个对象,一个是指向资源的指针,一个是控制块,指向一个引用计数对象。控制块中存储了强引用和弱引用的计数,强引用Uses代表shared_ptr对象的引用计数,弱引用Weaks代表weak_ptr对象的引用计数。
在这里插入图片描述
大概结构如上图所示,控制块其中也存储了指向资源的指针。
因此在构造一个shared_ptr对象的时候,会有两次堆分配,一次是为资源分配,一次是为控制块分配。因为每一个指向这份资源的指针对象都需要看到同一份引用计数,因此跟资源一样也是堆分配的。多次的堆分配和释放也就代表效率上的损失,而且极易产生内存碎片。

make_shared

C++11同时提供了make_shared函数,这是通过构造一个shared_ptr对象,而这个对象会事先申请一块足够大的内存空间,用于存放管理的资源以及控制块。即分配的堆空间是连续的,因此只有一次堆内存分配。

在这里插入图片描述
内存的结构就从左边的构造shared_ptr对象到右边的重构对象资源指针和引用计数。
相比shared_ptr构造,减少一次内存分配,提高效率,并且内存空间连续,减少内存碎片产生。但是,make_shared也存在缺点。

make_shared的缺点

自定义deleter

make_shared在构造智能指针对象的时候不能自定义deleter。在创建对象时同时创建控制块,这个控制块内部包含了引用计数、deleter等与管理资源相关的信息。因为资源和控制块是属于同一块申请的内存,所以使用自定义deleter可能会导致控制块内存被不正确地释放。因此,如果要使用deleter,应该使用shared_ptr直接构造。

构造函数

因为make_shared需要用到类的拷贝构造,因此需要被管理的类的构造函数是public的。

内存延迟归还

因为分配的空间是连续的,在资源指针的Uses变为0之后,控制块伴随资源的资源不会被立即释放,要等Weak也变为0,整块内存才被释放。资源只是被clear,但是但是没有归还操作系统。而如果是默认的控制块,在资源指针的Uses变为0之后,资源会被立即释放,内存立即归还。

通过调试看直接构造和make_shared的区别

void test2()
{std::shared_ptr<string> p1 = std::make_shared<std::string>(10, '9');{std::weak_ptr<std::string> wptr1;wptr1 = p1;std::shared_ptr<string> p2 = std::make_shared<std::string>("Hello");wptr1 = p2;p2 = p1;}std::cout << "end";
}void test1()
{std::shared_ptr<string> p1 = std::shared_ptr<std::string>(new std::string(10, '9'));{std::weak_ptr<std::string> wptr1;wptr1 = p1;std::shared_ptr<string> p2 = std::shared_ptr<std::string>(new std::string("Hello"));wptr1 = p2;p2 = p1;}std::cout << "end";
}int main()
{test1();test2();return 0;
}

直接构造在这里插入图片描述

当wptr指向p1的时候,可以看到p1的Weaks变为了2,weak_ptr观察到的内容与p1一致。并且注意此时control block的value显示为default,表示默认的控制块。
在这里插入图片描述
当weak_ptr指向p2,并且将p2指向p1,意思就是p2原来管理的Hello资源要释放掉,然后用p1拷贝构造一个对象,赋值给p2,让p1和p2同时管理10个9。
此时可以看到weak_ptr的资源指针已经显示Error reading,说明资源已经释放,内存已经归还了。

make_shared构造

在这里插入图片描述
此时可以看到原来为default的control block已经改为了make_shared。
在这里插入图片描述
重复之前的操作,把p2指向p1,再看weak_ptr的成员。可以看到ptr指向的资源并没有被释放,只是内容并清空而已。只有当weak_ptr的生命周期结束,整个内存块才会被释放,归还给操作系统。
这就是make_shared最主要的缺点,在某些内存要求高的场景下可能不太适用。

相关文章:

C++——shared_ptr:make_shared的用处,与shared_ptr直接构造的区别

shared_ptr shared_ptr继承自__shared_ptr&#xff0c;其中有两个对象&#xff0c;一个是指向资源的指针&#xff0c;一个是控制块&#xff0c;指向一个引用计数对象。控制块中存储了强引用和弱引用的计数&#xff0c;强引用Uses代表shared_ptr对象的引用计数&#xff0c;弱引…...

【网络安全带你练爬虫-100练】第17练:分割字符串

目录 一、目标1&#xff1a;使用函数分割 二、目标2&#xff1a;使用函数模块 三、目标3&#xff1a;使用正则匹配 一、目标1&#xff1a;使用函数分割 目标&#xff1a;x.x.x.x[中国北京 xx云] 方法&#xff1a;split函数replace函数 1、分割&#xff1a;使用split()方法将…...

Unity 之ToolTip的用法

文章目录 在Unity中&#xff0c;ToolTip是一个在编辑器中使用的UI元素&#xff0c;它提供了鼠标悬停在某个对象或控件上时显示的文本信息。ToolTip通常用于向开发人员提供有关对象、字段、控件或菜单项的附加信息&#xff0c;从而帮助他们更好地理解和使用这些元素。 ToolTip通…...

xsschallenge通关(11-15)

level 11 老规矩&#xff0c;先查看源码&#xff0c;做代码审计&#xff1a; <?php ini_set("display_errors", 0); $str $_GET["keyword"]; $str00 $_GET["t_sort"]; $str11$_SERVER[HTTP_REFERER]; $str22str_replace(">&quo…...

Kubernetes技术--k8s核心技术集群的安全机制RBAC

1.引入 我们在访问k8s的集群的时候,需要经过一下几个步骤: -a:认证 -1).传输安全:对外是不暴露端口:8080,只能够在内部访问,对外使用的是6443端口。 -2).客户端认证的常用几种方式: -https证书 基于ca证书 -https token认证 通过token识别用户 -https <...

【JavaSE】String类

两种创建String对象的区别 String s1 "hello"; String s2 new String("hello");s1是先查看常量池是否有 “hello” 数据空间&#xff0c;如果有就直接指向它&#xff0c;如果没有就创建然后指向它。s1最终指向的是常量池的空间地址。 s2是先在堆中创建空…...

DBMS Scheduler设置重复间隔

参考文档&#xff1a; Database Administrator’s Guide 29.4.5.2 Using the Scheduler Calendaring Syntax The main way to set how often a job repeats is to set the repeat_interval attribute with a Scheduler calendaring expression. See Also: Oracle Database…...

windows的redis配置sentinel

1、先安装好redis主从&#xff0c;参考我的文章&#xff0c;链接如下 redis主从&#xff08;windows版本&#xff09;_rediswindows版本_veminhe的博客-CSDN博客 2、然后配置sentinel 参考在windows上搭建redis集群&#xff08;Redis-Sentinel&#xff09; 配置时&#xf…...

NetMarvel机器学习促广告收益最大化,加速获客

游戏出海的竞争日益激烈&#xff0c;这并非空穴来风。 从2021年第一季度至2022年第四季度&#xff0c;iOS平台的CPI增长了88%&#xff0c;意味着厂商需要花费近两倍的钱才能获取一个新用户。与此同时数据隐私政策持续收紧&#xff0c;更加提高了营销成本。 在成本高涨的当下&…...

Spring-5.0.x源码下载及本地环境搭建

一、Spring源码下载 从github上下载Spring的源代码 下载地址&#xff1a;https://github.com/spring-projects/spring-framework 访问地址之后&#xff0c;打开Spring的代码页面找到你想下载的版本&#xff0c;如5.0.x&#xff0c;如下图所示&#xff1a; 下载方式一&#x…...

go中的切片

demo1:切片定义的几种方式 package mainimport "fmt"/* 切片定义的几种方式数组和切片区别&#xff1a; 使用数组传参是值传递&#xff0c;而使用切片传参是引用传递 数组定义好长度之后不可修改&#xff0c;而切片可以理解为动态数组&#xff0c;长度可修改*/func …...

C++笔记之单例通过GetInstance传递参数

C笔记之单例通过GetInstance传递参数 code review! 文章目录 C笔记之单例通过GetInstance传递参数例1.普通指针的单例例2.结合智能指针和std::call_once例3.编译不通过的错误例子&#xff0c;在GetInstance内不可以使用std::make_shared来创建对象 例1.普通指针的单例 运行 …...

1688API技术解析,实现获得1688商品详情

要实现获得1688商品详情&#xff0c;你需要使用1688 API。1688 API是阿里巴巴旗下的开放平台&#xff0c;它提供了一套丰富的接口&#xff0c;可以让开发者通过编程的方式获取到1688网站上的商品信息。 首先&#xff0c;你需要在阿里开放平台注册一个账号&#xff0c;并创建一…...

【Java 动态数据统计图】动态X轴二级数据统计图思路Demo(动态,排序,动态数组(重点推荐:难)九(131)

需求&#xff1a; 1.有一组数据集合&#xff0c;数据集合中的数据为动态&#xff1b; 举例如下&#xff1a; [{province陕西省, city西安市}, {province陕西省, city咸阳市}, {province陕西省, city宝鸡市}, {province陕西省, city延安市}, {province陕西省, city汉中市}, {pr…...

C#将text文本中的单双行分开单独保存

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 文本的分割1.设定text文件的名称为02.文本导出 文本的分割 1.设定text文件的名称为0 代码如下&#xff1a; using System; using System.Collections.Generic; us…...

深入理解 Go 语言中的 iota

iota是go语言的常量计数器&#xff0c;只能在常量表达式中使用&#xff0c;iota在const关键字出现时将被重置为0&#xff0c;const中每新增一行常量声明将使iota计数一次&#xff0c;可理解为const语句块中的行索引。它会自动递增&#xff0c;从0开始。 修改步长 尽管默认步长…...

【力扣】55、跳跃游戏

var canJump function(nums){let cover 0;for(let i0;i<nums.length;i){if(i<cover){cover Math.max(nums[i]i,cover);if(cover >nums.length-1){return true;}}}}...

个人与公司合作,怎么代开发票?有哪些优惠政策?

《梅梅谈税》专注于企业税务筹划&#xff01;助力企业合理、合规、合法进行节税税收筹划&#xff01; 当下越来越多的个人与公司直接发生业务往来&#xff0c;例如个人给企业提供技术服务&#xff0c;做宣传推广等&#xff0c;业务完成公司给个人支付了相关费用后&#xff0c;…...

什么是计算机视觉,计算机视觉的主要任务及应用

目录 1. 什么是计算机视觉 2. 计算机视觉的主要任务及应用 2.1 图像分类 2.1.1 图像分类的主要流程 2.2 目标检测 2.2.1 目标检测的主要流程 2.3 图像分割 2.3.1 图像分割的主要流程 2.4 人脸识别 2.4.1 人脸识别的主要流程 对于我们人类来说&#xff0c;要想认出身边…...

网易24届内推

【网易】2024届网易互联网秋季校园招聘内推开始啦&#xff01;给你分享我的专属内推邀请函&#xff1a;https://bole.campus.163.com/campus/home?projectId55&type99&isShare1&boleId7b842acc7c2b42db&boleType2&signatured5f2a3dc23bed70777a8be1a14b49…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域&#xff0c;Hive 作为 Hadoop 生态中重要的数据仓库工具&#xff0c;其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式&#xff0c;很多开发者常常陷入选择困境。本文将从底…...

[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...