关于C++智能指针复习总结
RAII(Resource Acquisition Is Initialization): 资源获得即初始化
利用对象生命周期来控制程序的资源(将资源交给对象处理) 智能指针利用了该思想
- 将资源交给一个对象, 初始化资源(可以是指针或者等等资源), 释放交给析构函数
因为析构函数无论是什么场景, 对象销毁时一定会被调用, 故此资源一定会被释放
智能指针
使用了RAII的思想管理动态内存分配的一个工具,以减少内存泄露的风险。
在使用上像一个普通指针一样操作(*和->)
头文件<memory.h>
auto_ptr(C++11及以后已被弃用)
- 拷贝→ 资源管理权转移(会导致原拷贝对象悬空)
即将原先的智能指针内容转换到新的智能指针内 - 该智能指针属于一个反面教材
template<typename T>
class auto_ptr { T* ptr;
public: explicit auto_ptr(T* p = nullptr) : ptr(p) {} ~auto_ptr() { delete ptr; } auto_ptr(const auto_ptr& other) : ptr(other.ptr) { other.ptr = nullptr; // 所有权转移!这是有问题的部分。 } auto_ptr& operator=(const auto_ptr& other) { if (this != &other) { delete ptr; // 删除当前对象所拥有的资源 ptr = other.ptr; // 获取新资源的所有权 other.ptr = nullptr; // 将原所有者的指针设为 nullptr } return *this; } T& operator*() const { return *ptr; } T* operator->() const { return ptr; }
};
unique_ptr
一个智能指针只能管理一个指针对象(不支持赋值和拷贝)
- 从类的语法角度将拷贝构造和赋值用delete关键字删除, 使得无法复制
- 并没有从根上解决auto_ptr的问题
template<typename T>
class unique_ptr { T* ptr;
public: unique_ptr(T* p = nullptr) : ptr(p) {} ~unique_ptr() { delete ptr; } // 手动禁止拷贝和赋值unique_ptr(const unique_ptr& other) = delete; unique_ptr& operator=(const unique_ptr& other) = delete; // 移动构造和赋值unique_ptr(unique_ptr&& other) noexcept : ptr(other.ptr) { other.ptr = nullptr; } unique_ptr& operator=(unique_ptr&& other) noexcept { if (this != &other) { delete ptr; ptr = other.ptr; other.ptr = nullptr; } return *this; } T& operator*() const { return *ptr; } T* operator->() const { return ptr; } explicit operator bool() const { return ptr != nullptr; }
};
shared_ptr
可以表示用多个智能指针管理同一个指针对象(支持赋值和拷贝)
-
使用引用计数来实现
- 每个对象生成时计数++
- 对象释放时计数–
- 计数为0时则释放所管理的资源
-
实现shared_ptr
-
不能使用静态成员变量, 如此静态成员变量是属于整个类, 所有的智能指针对象都会共享该计数(我们应该不同的智能指针对象拥有不同的计数)
-
应在shared_ptr中添加一个计数指针(指针保存的为地址, 可以在不同对象内传递)在构造中初始化为1, 拷贝时将计数也拷贝+1,在析构时将对应的计数指针–即可
template<typename T> class shared_ptr { T* ptr; int* count; public: shared_ptr(T* p = nullptr) : ptr(p), count(new int(1)) {} shared_ptr(const shared_ptr& other) : ptr(other.ptr), count(other.count) { ++(*count); } ~shared_ptr() { if (--(*count) == 0) { delete ptr; delete count; } } shared_ptr& operator=(const shared_ptr& other) { if (this != &other) { if (--(*count) == 0) { delete ptr; delete count; } ptr = other.ptr; count = other.count; ++(*count); } return *this; } T& operator*() const { return *ptr; } T* operator->() const { return ptr; } }; -
shared_ptr的问题
-
循环引用(无法在内部解决), 需要使用weak_ptr解决
weak_ptr主要用shared_ptr构造, 用于解决循环引用问题- 当一个自定义类型内也存在多个shared_ptr时, 两个及以上个自定义类型通过shared_ptr互相指向时则会出现循环引用的问题
- weak_ptr不会增加对应shared_ptr的引用计数(即不参与资源管理)
但是仍旧可以像指针一样使用weak_ptr(可以访问和修改资源)
struct Node {int _val;//成员包含shared_ptr类型, 去管理其它对象时会对应增加计数/*std::shared_ptr<Node> _next;std::shared_ptr<Node> _prev;*///管理其它对象时不会增加对应计数std::weak_ptr<Node> _next;std::weak_ptr<Node> _prev;~Node(){cout << "~Node" << endl;} };// 循环引用 -- weak_ptr不是常规智能指针,没有RAII,不支持直接管理资源 // weak_ptr主要用shared_ptr构造,用来解决shared_ptr循环引用问题 void test_shared_ptr2() {/*std::shared_ptr<Node> n1(new Node);std::shared_ptr<Node> n2(new Node);//通过成员进行了相互引用, 则彼此"缠绕"了起来//n1的_next释放需要依赖指针类型的析构, 结点的析构需要依赖所在对象的析构, 但所在对象的析构又依赖于n2的_prev的析构(当_prev析构了, node1才会被析构); 反之类似, 故彼此缠绕, 形成循环引用n1->_next = n2;//增加了node2的计数n2->_prev = n1;//增加了node1的计数*/std::shared_ptr<Node> n1(new Node);std::shared_ptr<Node> n2(new Node);cout << n1.use_count() << endl;cout << n2.use_count() << endl;n1->_next = n2;n2->_prev = n1;cout << n1.use_count() << endl;cout << n2.use_count() << endl; }
weak_ptr
一般都作为shared_ptr的辅助指针, 解决其循环引用的问题, 它只会指向资源, 而不参与管理资源(即不会增加引用计数)
删除器
关于new和new[]生成的指针对应delete和delete[]的问题(是否匹配使用, 释放空间)
- 为什么存在删除器 ?
- new和new[]底层都是调用了operator new函数, 然后调用了malloc以及对应对象的构造函数,但区别在于new[]在malloc时多malloc了4个字节存在首部(用于delete[]时对应找到malloc了多少个对象空间)
- delete和delete[]底层都是调用了operator delete, 然后调用了对应对象的析构和free,区别在于delete调用了一次析构和一次free, 但delete[]调用了n次析构和1次free
但在析构时,指针会往前偏移4个字节找到总构造的对象个数所对应的空间, 然后依次调用析构和free - 如果是new[]出来的对象使用delete释放时, 由于delete不会进行偏移, 会导致free的位置不正确, 导致程序崩溃
- 定制删除器
- 仿函数
- lambda表达式
- 不同的智能指针对应的删除器
- shared_ptr可在构造函数内传入仿函数或者lambda表达式
- unique_ptr只能从模板参数传入
相关文章:
关于C++智能指针复习总结
RAII(Resource Acquisition Is Initialization): 资源获得即初始化 利用对象生命周期来控制程序的资源(将资源交给对象处理) 智能指针利用了该思想 将资源交给一个对象, 初始化资源(可以是指针或者等等资源), 释放交给析构函数 因为析构函数无论是什么场景, 对象销毁时一定会…...
Prometheus Operator创建告警规则并接入钉钉报警
prometheus之钉钉报警 前言1. 添加prometheus报警规则1.2 添加自定义报警规则文件 2. 配置钉钉报警2.2 部署dingding插件 3. 编写alertmanager配置文件 前言 在kubenetes上安装了kube-promethues(包含Prometheus Operator),程序正常跑起来了,…...
Word整理论文参考文献
1.安装Zotero软件 2.安装Zotero的Chrome网站插件,并将插件固定到浏览器 3.安装Word的Zotero插件 4.在DBLP网站https://dblp.org/search 搜索需要添加的参考文献->点击BibTex->点击网页右上角的Zotero符号(即第二步所指的符号)->至…...
计算机网路概述
目录 计算机网络的概念 计算机网络的定义: 计算机网络的组成: 终端系统/资源子网 通信子网 计算机网络的类型 按照拓扑分类编辑 按照范国分类: 按传输方式进行分类 计算机网络体系结构 传输方式 按照传输方向区分 按照传输对象…...
832. 翻转图像 - 力扣
1. 题目 给定一个 n x n 的二进制矩阵 image ,先 水平 翻转图像,然后 反转 图像并返回 结果 。 水平翻转图片就是将图片的每一行都进行翻转,即逆序。 例如,水平翻转 [1,1,0] 的结果是 [0,1,1]。 反转图片的意思是图片中的 0 全部被…...
mumu 模拟器安装
1.下载安装 下载地址 Win 历史版本:http://mumu.163.com/update/win/Mac 历史 版本:http://mumu.163.com/20200515/25905_880858.html 2.设置为竖屏 在设置中心--界面设置页面设置宽720,高1280,DPI为240,如下图所示。…...
opencv实现图片的膨胀腐蚀
opencv实现图片的膨胀腐蚀 在OpenCV中,膨胀和腐蚀是两种基本的图像处理操作,通常用于二值图像中以提取特定的特征。它们是基于图像的形态学操作,使用一个称为结构元素或核的模板来改变图像的形状。 下面是如何使用OpenCV实现图片的膨胀和腐…...
[AIGC] Java常用的JSON库及简单示例
Java常用的JSON库及简单示例 在Java的世界里,JSON库广泛用于日常开发工作,本文将介绍几个常用的JSON库并配以简单的示例代码。 1. Gson Gson是Google提供的一个用来在Java对象和JSON数据之间进行转换的Java库。 它有一定的学习曲线,但一旦熟…...
Linux shell编程学习笔记50:who命令
0 前言 2024年的网络安全检查又开始了,对于使用基于Linux的国产电脑,我们可以编写一个脚本来收集系统的有关信息。比如,我们可以使用who命令来收集当前已登陆系统的用户信息,当前运行级别等信息。 1. who命令 的功能、格式和选项…...
vue使用webscoket
1. 创建 WebSocket 连接 首先,你需要在你的 Vue 组件中创建一个 WebSocket 连接。通常,这会在组件的 created 或 mounted 生命周期钩子中完成。 created() {this.socket new WebSocket(wss://your-websocket-url);this.socket.onopen () > {conso…...
第18章-综合以上功能 基于stm32的智能小车(远程控制、避障、循迹) 基于stm32f103c8t6/HAL库/CubeMX/超详细,包含代码讲解和原理图
这个是全网最详细的STM32项目教学视频。 第一篇在这里: 视频在这里 STM32智能小车V3-STM32入门教程-openmv与STM32循迹小车-stm32f103c8t6-电赛 嵌入式学习 PID控制算法 编码器电机 跟随 第18章-综合以上功能 18-按键和app按钮切换功能 根据上面介绍,我们的模式可…...
java并发工具类都有哪些
Java中的并发工具类包括: CountDownLatch CountDownLatch允许一个或多个线程等待其他线程完成某些操作。它通常用于线程间的同步,例如在一个线程完成其工作后通知其他线程继续执行。 CyclicBarrier CyclicBarrier是一个同步辅助类,它允许一…...
偏微分方程算法之抛物型方程差分格式编程示例一
目录 一、研究问题 二、C++代码 三、结果分析 一、研究问题 从本节开始将对具体的抛物型偏微分问题算例进行C++编程,以加深对抛物型偏微分方程差分格式构造的理解和应用。 采用向前欧拉格式计算抛物型方程初边值问题:...
数据结构—栈(C语言实现)
文章目录 前言一、栈的概念二、栈的代码实现Stack.hStack.c 三、使用栈解决有效的括号问题总结 前言 小伙伴们,大家好哇!!欢迎来到我的博客! 今天来分享一下另外一种数据结构—栈。主要包括栈的基本概念与其代码实现,…...
JVM学习-垃圾回收器(一)
垃圾回收器 按线程数分类 串行垃圾回收器 串行回收是在同一时间段内只允许有一个CPU用于执行垃圾回收操作,此时工作线程被暂停,直至垃圾收集工作结束 在诸如单CPU处理器或者较小的应用内存等硬件平台不是特别优越的场合,串行回收器的性能表…...
dolphinscheduler standalone安装
官方文档:https://dolphinscheduler.apache.org/en-us/docs/3.1.3/guide/installation/standalone 1.安装(以放在/home为例) 下载见:https://download.csdn.net/download/taotao_guiwang/89311365 tar -xvzf apache-dolphinsche…...
力扣hot 100:49. 字母异位词分组(python C++)
目录 题目描述:题解(python):(方法一:排序)代码解析代码运行解析 题解(C):(方法一:排序)代码解析&运行解析 原题目链接…...
男士内裤什么材质的好?推荐男士内裤的注意事项
天气已经逐渐热了起来,广大男士们在夏天难免会出一身的汗,不少男士朋友都觉得一些吸湿性、透气性不好的内裤会在夏天穿着很不适,想挑选一些比较适合夏天的男士内裤,但现在的男士内裤品牌和材质分类却比较多,看得大家眼…...
Python操作MySQL数据库的工具--sqlalchemy
文章目录 一、pymysql和sqlalchemy的区别二、sqlalchemy的详细使用1.安装库2.核心思想3.整体思路4.sqlalchemy需要连接数据库5.使用步骤1.手动提前创建数据库2.使用代码创建数据表3.用代码操作数据表3.1 增加数据3.2 查询数据3.3 删除数据3.4 修改数据 一、pymysql和sqlalchemy…...
【算法】排序
排序算法在信息学非常常用。Hello!大家好,我是学霸小羊,今天讲几个排序算法。 1.“打擂台”排序 思路:a[ i ]和a[ j ]打擂台(i<j)。 这个方法简单易懂,只需要看看需不需要交换。按从大到小…...
深入理解 MCP 协议:原理、架构与实战开发指南
前言 2024年底 Anthropic 发布了 MCP(Model Context Protocol),短短几个月内 GitHub 星标突破 8 万。这个协议解决了一个核心问题:如何让大模型标准化地连接外部工具和数据源。 本文将从协议设计原理出发,手把手带你实…...
Ubuntu 18.04环境下小米K30U内核编译实战与排错指南
1. 项目概述与核心价值最近在折腾一台小米K30U,想给它刷个自定义内核,体验一下超频或者优化调度。但网上的教程要么是针对新机型,要么就是环境配置说得不清不楚,特别是对于Ubuntu 18.04这个已经有点“年迈”但依然稳定的系统版本&…...
2026年十家小程序开发公司榜单及全面解读
数字经济全行业渗透的当下,权威的小程序开发服务商排名,早已成为企业筛选技术合作方的核心参考坐标。市面上服务商定位差异大、水平参差不齐,企业如何才能找到技术实力过硬、同时匹配自身成本预期的合作方?本文结合2024-2025年行业…...
WarcraftHelper:5分钟解决魔兽争霸III现代兼容性问题的终极指南
WarcraftHelper:5分钟解决魔兽争霸III现代兼容性问题的终极指南 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为经典魔兽争霸III在W…...
【2026 Q1实测数据】ChatGPT新增“因果推理引擎”准确率提升至89.7%,但83%用户因忽略这4个参数设置导致失效
更多请点击: https://codechina.net 第一章:ChatGPT“因果推理引擎”的架构演进与2026 Q1实测基准 OpenAI于2025年Q4正式将ChatGPT核心推理模块重构为“因果推理引擎”(Causal Reasoning Engine, CRE),其本质是将传统…...
ARM SVE向量化技术解析与性能优化实践
1. ARM SVE向量化技术解析 1.1 SVE架构设计理念 ARM可扩展向量扩展(Scalable Vector Extension, SVE)是ARMv8-A和ARMv9-A架构引入的长向量指令集,其核心创新在于向量长度无关(Vector Length Agnostic, VLA)的设计哲学。与传统固定长度的SIMD指令(如x86的…...
【Go i18n】TOML语言包
一、VS Code 必备的 TOML 插件1. Even Better TOML(核心高亮与语法检查 👑)搜索关键字:Even Better TOML为什么要装:它是目前全网公认第一的 TOML 插件。装上它之后,你的 .toml 文件不仅会变得色彩斑斓&…...
m4s-converter:3步解锁B站缓存视频的跨平台免费工具
m4s-converter:3步解锁B站缓存视频的跨平台免费工具 【免费下载链接】m4s-converter 一个跨平台小工具,将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾因B站视频突然下架而感到…...
Unity接入海康UMP流全流程:签名认证、HTTP长连接与自定义渲染
1. 这不是简单的“拉流”,而是一场跨协议、跨权限、跨引擎的精准对接你有没有试过在Unity里直接填一个RTSP地址,比如rtsp://admin:123456192.168.1.64:554/Streaming/Channels/101,然后点播放——结果黑屏、报错、卡死,或者更糟&a…...
【CDA干货】用这4种数据分析思维,拆解爆款视频密码
很多做视频的人,发视频全凭感觉。今天视频火了,不知道为什么;明天流量掉了,也不知道哪里出了问题。其实,爆款背后从来不是运气,而是数据的逻辑。用数据分析思维做视频账号,就是把那些说不清道不…...
