当前位置: 首页 > 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…...

实测Claude 4.5 Opus重构“屎山”代码:手把手教你用AI给遗留项目做外科手术(附前后对比与单元测试生成)

实测Claude 4.5 Opus重构“屎山”代码&#xff1a;手把手教你用AI给遗留项目做外科手术&#xff08;附前后对比与单元测试生成&#xff09; 接手一个满是"祖传代码"的老旧项目&#xff0c;就像被丢进一座迷宫——变量命名像密码&#xff0c;函数逻辑像意大利面&…...

AI编程实战:工具选型、效率提升与代码优化技巧

2026年&#xff0c;AI编程已进入“自动驾驶时代”&#xff0c;据行业数据显示&#xff0c;AI编程工具可使开发者效率提升30%-70%&#xff0c;中小企业开发成本降低70%&#xff0c;个人开发者可快速实现产品落地。对于开发者而言&#xff0c;熟练运用AI编程工具&#xff0c;不是…...

Java TCC到底要不要用?90%团队踩坑的4个认知误区,今天一次性说透

第一章&#xff1a;Java TCC到底要不要用&#xff1f;90%团队踩坑的4个认知误区&#xff0c;今天一次性说透TCC&#xff08;Try-Confirm-Cancel&#xff09;作为分布式事务的一种经典模式&#xff0c;在 Java 生态中常被误认为“高可用银弹”或“微服务标配”。但真实生产实践中…...

Android 15 音频子系统(八):Audio HAL 与硬件接口——音频数据的最后一公里

引言:最后一公里的旅程 如果把 Android 音频系统比作一条物流网络,那么 AudioFlinger 是"中央分拣中心",AudioPolicy 是"路由规划师",而 Audio HAL(Hardware Abstraction Layer)就是最终把包裹送到用户手里的"快递员"。 前几篇我们聊了 …...

uniApp实现跨平台跳转支付宝小程序的完整方案

1. 跨平台跳转支付宝小程序的背景与挑战 在移动应用开发中&#xff0c;实现应用间的无缝跳转是提升用户体验的关键环节。对于使用uniApp框架的开发者来说&#xff0c;如何在不同操作系统上正确唤起支付宝小程序&#xff0c;是一个既常见又棘手的问题。iOS和Android平台在协议处…...

Qwen3.5-35B-A3B-AWQ-4bit图文理解入门:支持中文的图片问答新手必学5个技巧

Qwen3.5-35B-A3B-AWQ-4bit图文理解入门&#xff1a;支持中文的图片问答新手必学5个技巧 1. 认识Qwen3.5图文理解模型 Qwen3.5-35B-A3B-AWQ-4bit是一款专为视觉多模态理解设计的量化模型&#xff0c;它能像人类一样"看懂"图片内容并进行智能对话。这个模型特别适合需…...

2026别墅地下室保养升值的最好方法:电渗透技术的应用

别墅地下室随着人们日益增长的生活质量&#xff0c;功能也逐渐变得丰厚。当今时代不少业主都会在地下室加装健身房&#xff0c;酒窖以及影视厅等。这些功能区建设完毕初期给人无不良影响&#xff0c;但是随着时间的渐长&#xff0c;湿气不断渗透&#xff0c;首先空气潮湿度会给…...

忍者像素绘卷效果展示:云端画布背景+金橙配色+浮雕UI真实渲染效果

忍者像素绘卷效果展示&#xff1a;云端画布背景金橙配色浮雕UI真实渲染效果 1. 视觉风格惊艳呈现 忍者像素绘卷带来了全新的视觉体验&#xff0c;将传统像素艺术与现代设计理念完美融合。这款基于Z-Image-Turbo深度优化的图像生成工具&#xff0c;创造了一个明亮通透的创作环…...

Pixel Epic · Wisdom Terminal 处理403 Forbidden等HTTP错误:智能诊断与修复建议

Pixel Epic Wisdom Terminal 处理403 Forbidden等HTTP错误&#xff1a;智能诊断与修复建议 1. 引言&#xff1a;HTTP错误的困扰与解决方案 每个Web开发者和运维人员都遇到过这样的场景&#xff1a;用户反馈页面打不开&#xff0c;你打开开发者工具一看&#xff0c;赫然显示4…...

Java网络协议解析核心源码剖析(Netty+Spring Boot双栈实测):从Raw Socket到自动反序列化全链路解密

第一章&#xff1a;Java网络协议解析核心源码剖析&#xff08;NettySpring Boot双栈实测&#xff09;&#xff1a;从Raw Socket到自动反序列化全链路解密Java 网络通信的底层能力并非止步于 Spring Boot 的 RestController 抽象层——其真实脉搏深埋于 Netty 的 ChannelPipelin…...