【C++深陷】之shared_ptr
0. 什么是智能指针
使用new 和delete 手动进行动态内存管理很容易出现内存泄漏等问题。C++11为了更安全、更方便的管理动态内存,新的标准库提供了两种智能指针(smart pointer):shared_ptr和unique_ptr,以及一个伴随类weak_ptr。
这三种类型定义在memory头文件中。
当指向某对象的最后一个shared_ptr被销毁时,shared_ptr类会自动帮助我们销毁开辟的动态内存。unique_ptr因为独占所指向的对象,不允许拷贝、赋值等操作,在其被销毁时也会帮助我们自动的销毁动态内存。
本文主要介绍shared_ptr。
1. 创建与初始化
智能指针也是类模板,因此需要尖括号指定指针的类型。
#include <memory>int main() {std::shared_ptr<string> p1; // 可以指向string, 但此时指针的值是未初始化的未定义值,依旧不安全std::shared_ptr<list<int>>p2; // 可以指向int的listreturn 0;
}
可以使用标准库函数std::make_shared进行声明和初始化,是一种更加安全的方式。
auto p3 = std::make_shared<string>(10, 's'); // p3指向一个string, string的值是「ssssssssss」
std::cout << p3 << " -> " << *p3; // 输出: 0x7fa9d6904098 -> ssssssssss
智能指针完全可以当做正常指针使用,直接使用*解引用运算符可以直接得到指针指向的值。
2. 使用
shared_ptr就是一个类模板,通过运算符重载、构造函数、析构函数等C++面向对象的特性,外加引用计数规则,将动态内存管理这件事情屏蔽给了编程者。
shared_ptr支持的操作不多,*和->可以把智能指针当做原生指针一样使用。其他的属于shared_ptr类的操作。
可以直接跑下面的例子。
#include <iostream>
#include <memory>int main() {auto smart_ptr = std::make_shared<std::string>(10, 's');// 不能像如下形式的赋值初始化// std::shared_ptr<string> p0 = new string(10, 's');// 必须显示调用// p1也指向一个动态内存, 内存是一个string, string的内容是「ssssssssss」auto p1(smart_ptr);// 解引用运算符访问对象, 输出: 0x7fa9d6904098 -> ssssssssssstd::cout << smart_ptr << " -> " << *smart_ptr << std::endl;// 箭头运算符调用对象函数, 等价于 (*.smart_ptr).size(), 调用string的size函数// 输出: 10std::cout << smart_ptr->size() << std::endl;// 这里就不能用 nullptr == smart_ptr 判断了if (smart_ptr) {std::cout << "指针有效" << std::endl; // 输出} else {std::cout << "指针无效" << std::endl;}auto p2 = smart_ptr;// 输出: 3, 0std::cout << smart_ptr.use_count() << ", " << smart_ptr.unique() << std::endl;// use_count为1, unique返回true, 否则返回false; 这里输出的时候讲bool类型转换为int类型了// get方法得到裸指针类型, !!!尽量不要使用std::string *p0 = smart_ptr.get();// 退出程序的时候不用delete smart_ptr// 会自动销毁return 0;
}
3. 引用计数原理
一共4个关键点:
- 构造函数,引用计数初始化为1
- 拷贝构造函数,引用计数 +1
- 赋值运算符, 右边引用计数 +1,左边原来指向的对象 -1。若左侧的原来指向的对象引用计数归0,则清理原来对象的内存
- 退出作用域后,清理局部变量,调用智能指针的析构函数,引用计数 -1。若引用计数归0, 在析构函数中清理内存
其实用类的静态成员变量可以实现上述引用计数功能,但是C++标准只规定了引用计数的行为,并没有规定具体的实现方案,因此不能说就是用静态成员变量实现的。
int main() {// 1. 构造函数, 引用计数初始化为1std::shared_ptr<std::string> p0(new std::string("str0"));std::shared_ptr<std::string> p1(new std::string("str1"));// 输出: 「str0: 1, str1: 1」cout << *p0 << ": " << p0.use_count() << ", " << *p1 << ": " << p1.use_count() << endl;// 2. 拷贝构造函数, 引用计数 +1auto p2(p0), p3 = p0;// 输出: 「str0: 3, str1: 1」cout << *p0 << ": " << p0.use_count() << ", " << *p1 << ": " << p1.use_count() << endl;// 3. 赋值运算符, 右边的引用计数 +1, 左边的原来指向的对象 -1// 若p2原来指向的对象引用计数为0了, 则清理原来对象的内存p2 = p1;// 输出: 「str0: 2, str1: 2」cout << *p0 << ": " << p0.use_count() << ", " << *p1 << ": " << p1.use_count() << endl;// 4. 退出程序后依次析构上述变量, p0、p1、p2、p3引用计数依次减1// 若引用计数归0, 在析构函数中清理内存return 0;
}
相关文章:
【C++深陷】之shared_ptr
0. 什么是智能指针 使用new 和delete 手动进行动态内存管理很容易出现内存泄漏等问题。C11为了更安全、更方便的管理动态内存,新的标准库提供了两种智能指针(smart pointer):shared_ptr和unique_ptr,以及一个伴随类we…...
SpringMVC中遇到的错误
SpringMVC中遇到的错误1.web.xml中配置SpringMVC核心类: DispatcherServlet 报错解决方案:添加Tomcat包2. not declaration can be found for element--------‘mvc:annotation-driven‘通配符的匹配很全面, 但无法找到元素 mvc:annotation-driven 的声明解决方案&a…...
姿态估计端到端新方案 | DirectMHP:用于全范围角度2D多人头部姿势估计
前言 现有的头部姿势估计主要集中在具有预先检测到的正面头部的单个人,这依赖于单独训练的面部检测器,不能很好地泛化到完整的视点。在本文中,作者关注全范围 MPHPE 问题,并提出了一个名为 DirectMHP 的直接端到端简单基线&#x…...
jvm学习的核心(五)---垃圾回收算法和常见垃圾回收器
文章目录1.垃圾回收算法**1.1. 标记阶段****1.2. 清除阶段**1.2.1.标记清除算法1.2.2.标记复制算法1.2.3.标记整理算法1.3.引用2.常见的垃圾回收器2.1.Serial回收器2.2.ParNew回收器2.3.Parallel回收器2.4.CMS回收器<font color red>2.5.G1垃圾回收器ZGC回收器ÿ…...
亿级高并发电商项目-- 实战篇 --万达商城项目 二(Zookeeper、Docker、Dubbo-Admin等搭建工作
👏作者简介:大家好,我是小童,Java开发工程师,CSDN博客博主,Java领域新星创作者 📕系列专栏:前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 Ǵ…...
【C#基础】 C# 数据类型总结
序号系列文章0【C#基础】初识编程语言C#1【C#基础】C# 程序通用结构总结2【C#基础】C# 程序基础语法解析文章目录前言数据类型一. 值类型(Value types)二. 引用类型(Reference types)三. 指针类型(Pointer types&#…...
格子玻尔兹曼法介绍
1 LBM简介格子玻尔兹曼法(Lattice Boltzmann Method)简称LBM,是一种CFD算法,可求解流动、传热等常见CFD问题。LBM基于格子玻尔兹曼方程(LBE),从介观尺度(mesoscope)描述了…...
活动星投票在时间的河流上造园分组怎么设置如何进行分组报名
“在时间的河流上造园”网络评选投票_免费小程序运行系统_企业有关的投票_微信投票的应用小程序投票活动如何做?很多企业在运营当中,都会通过投票活动来进行推广,从而达到吸粉、增加用户粘度等效果。而此类投票活动,通过小程序就可…...
c#小笔记本-基础
c#基本知识一.基础操作1.打印-writeline,write2.输入-readline,readkey二.变量1.折叠代码-#region,#endregion2.变量类型(在c语言变量类型上新增的)三.常量-const四.转义字符五.显示转换1.括号强转-低精度装高精度2.parse法-作用于字符串3.co…...
DamiCMS SQL注入分析
2023年将会持续于B站、CSDN等各大平台更新,可加入粉丝群与博主交流:838681355,为了老板大G共同努力。 一、入口文件(单入口文件模式) 看一下Index.php文件代码:引入了php_safe.php文件 查看一下php_safe.php防御文件: 对变量e…...
图傅里叶变换的推导和理解
把传统的傅里叶变换以及卷积迁移到Graph上来,核心工作其实就是把拉普拉斯算子的特征函数 e − i ω t e^{-i\omega t} e−iω...
Java八股文(Java面试题)
JDK、JRE、JVM 三者之间的关系?JDK(Java Development Kit):是Java开发工具包,是整个Java的核心,包括了Java运行环境JRE、Java工具和Java基础类库。它能够创建和编译程序。JRE(Java Runtime Envi…...
java ssm idea高校图书借阅管理系统设计2z87z
本论文是以构建高校图书管理系统设计为目标,使用 jsp制作,由前台用户图书借阅、后台管理员图书分类两大部分组成。着重论述了系统设计分析,系统的实现(用户注册模块,用户登录,用户图书借阅模块,…...
电脑重装系统注册表恢复方法
今天讲关于大家的电脑在遇到一些故障的时候,以及电脑用久了之后会卡顿,那么这时候大家一般都会给电脑重装系统。重装系统之后却发现自己电脑里的注册表不见了,重装系统后怎么恢复注册表?小编就带着大家一起学习重装系统注册表恢复到底是怎…...
信道建模(大尺度、小尺度、莱斯衰落、瑞利衰落、莱斯信道、瑞利信道)
一、大尺度衰落与小尺度衰落 大尺度衰落由收发两端的距离决定,功率上建模为: 小尺度衰落由收发两端的环境决定,比如是否有遮挡,场景有室内、室外、平原、山村、城镇等,这些环境影响到收发两端是否有直达链路࿰…...
2022年12月电子学会Python等级考试试卷(四级)答案解析
青少年软件编程(Python)等级考试试卷(四级) 一、单选题(共25题,共50分) 1. 有n个按名称排序的商品,使用对分查找法搜索任何一商品, 最多查找次数为5次,则n的值可能为?&…...
通过实例告诉你lua中ipairs到底是怎么遍历的!
这个的文章挺多的,但是有好几种说法并且不全。有人说是忽略手动设定值,有人说是从1开始数,直到序号断开,还有人给出结果,但是和我实机测试的效果不一样, 所以我自己总结一篇。经过我的测试和总结得到以下结…...
Axios异步请求 json格式
Axios是Ajax的一个框架,简化Ajax操作。需要axios.min.js 和vue.js的jar。发送普通参数异步请求以及相应异常情况客户端向服务器端异步发送普通参数值:- 基本格式: axios().then().catch()- 示例:axios({ // axios表示要发送一个异步请求metho…...
Postgresql源码(100)Portal与事务的关系(顶层事务与子事务)
1 总结 portal与事务有强绑定的关系,由portal->createSubid变量记录关联关系。如果为1表示顶层事务,关联的是子事务。 不论是顶层事务还是子事务,提交、回滚时只会处理自己创建出来的portal。 顶层事务会清理非活跃状态的Portalÿ…...
Java、JSP企业快信系统的设计与实现
技术:Java、JSP等摘要:计算机网络的出现到现在已经经历了翻天覆地的重大改变。因特网也从最早的供科学家交流心得的简单的文本浏览器发展成为了商务和信息的中心。到了今天,互联网已经成为了大量应用的首选平台,人们已经渐渐习惯了…...
Mac开发者必备:OpenClaw调试QwQ-32B代码补全全流程
Mac开发者必备:OpenClaw调试QwQ-32B代码补全全流程 1. 为什么选择OpenClaw作为代码助手 作为一名长期在Mac上开发的全栈工程师,我一直在寻找能够真正融入工作流的智能编码工具。直到遇到OpenClaw,才发现这个开源的本地化AI智能体框架完美契…...
STM32开发中的C语言高效编程技巧
STM32开发中的C语言高效编程技巧1. 位操作在寄存器控制中的应用1.1 位操作基础在STM32嵌入式开发中,C语言提供了六种基本位操作运算符:&按位与|按位或^按位异或~按位取反<<左移>>右移1.2 寄存器位操作技巧1.2.1 特定位置位/清零// 设置G…...
OpenClaw负载均衡:多Qwen3-VL:30B实例轮询策略
OpenClaw负载均衡:多Qwen3-VL:30B实例轮询策略 1. 为什么需要多模型实例负载均衡 上周我遇到一个棘手问题:用OpenClaw处理批量图片分析任务时,单个Qwen3-VL:30B实例频繁触发速率限制,导致任务队列堆积。更糟的是,有次…...
Python制作简易PDF查看工具——PDFViewerV1.0
PDFViewer PDF浏览工具,是使用Python语言(使用PyQt5开发界面,PDF解析使用PyMuPDF开源模块)开发的PDF查看工具,已经实现基本翻页浏览、OCR文字识别(基于开源主流文字识别模型实现)、内容查找高亮…...
英雄联盟智能助手:5个核心功能彻底改变你的游戏体验
英雄联盟智能助手:5个核心功能彻底改变你的游戏体验 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 还在为繁琐的游戏…...
别再自己造轮子了!用Python HAPI一键搞定HITRAN/HITEMP光谱计算(附避坑指南)
别再重复造轮子!用Python HAPI高效处理HITRAN/HITEMP光谱数据 在光谱分析领域,许多研究者都曾陷入过这样的困境:为了计算某种气体的光谱特性,花费数周甚至数月时间研读文献、编写算法,结果却发现计算效率低下且结果难以…...
4个步骤让普通用户实现黑苹果EFI自动生成:OpCore Simplify智能工具全解析
4个步骤让普通用户实现黑苹果EFI自动生成:OpCore Simplify智能工具全解析 【免费下载链接】OpCore-Simplify A tool designed to simplify the creation of OpenCore EFI 项目地址: https://gitcode.com/GitHub_Trending/op/OpCore-Simplify 如何用智能工具解…...
深蓝词库转换:20+输入法词库互通的完整实战指南
深蓝词库转换:20输入法词库互通的完整实战指南 【免费下载链接】imewlconverter ”深蓝词库转换“ 一款开源免费的输入法词库转换程序 项目地址: https://gitcode.com/gh_mirrors/im/imewlconverter 你是否曾在切换输入法时,为无法迁移多年积累的…...
Unity游戏开发:A*寻路算法实战,5步搞定NPC智能移动(附完整Demo)
Unity游戏开发:A*寻路算法实战指南与高级优化技巧 在游戏开发中,NPC的智能移动一直是开发者需要解决的核心问题之一。想象一下,当玩家在《魔兽世界》中穿越荆棘谷时,那些巡逻的巨魔守卫是如何绕过树木和山丘找到最短路径的&#x…...
AS3935闪电传感器Arduino驱动库深度解析与工业级应用
1. 项目概述AS3935 是一款由 AMS(现为 ams OSRAM)推出的专用闪电检测传感器芯片,集成 RF 前端、数字信号处理器(DSP)、闪电算法引擎及 IC/SPI 接口,可实现对 40 km 范围内云地闪(CG)…...
