c++-智能指针
1、概念
堆内存的对象需要手动使用delete销毁,如果忘记使用delete销毁就会造成内存泄漏。
所以C++在ISO 98标注中引入了智能指针的概念,并在C++11 中趋于完善。
使用智能指针可以让堆内存对象具有栈内存对象的特性。原理时给需要自动回收的堆内存对象套上一层栈内存的模板类对象即可。

C++有四种智能指针:
- auto_ptr (自动指针,已经废弃)(C++ISO 98)
- unique_ptr (唯一指针)(C++ISO 11)
- shared_ptr (共享指针)(C++ISO 11)
- weak_ptr (协助指针)(C++ISO 11)
使用智能指针需要引入头文件#include<memory>
2、auto_ptr
#include <iostream>
#include <memory>
using namespace std;
class Test
{
private:
string s;
public:
Test(string s):s(s)
{
cout << s << "构造函数" << endl;
}
~Test()
{
cout << s << "析构函数" << endl;
}
void show()
{
cout << s << "执行程序" << endl;
}
};
int main()
{
{
Test *t1 = new Test("A");
// 创建一个智能指针管理t1
auto_ptr<Test> ap1(t1); // ap1 管理t1
// 取出被管理的堆内存对象,并调用show成员函数
ap1.get()->show();
// 释放控制权
// ap1.release();
// 创建B堆对象,B将A顶掉,A对象销毁
ap1.reset(new Test("B"));
ap1.get()->show(); // 释放控制权并且销毁资源对象
ap1.reset();
cout << "局部代码块执行结束" << endl;
}
return 0;
} 
释放对象不会调用析构函数,只有销毁对象才会有

由于成员变量存在指针类型,因此拷贝构造函数与赋值运算符的使用会出现问题。与浅拷贝的问题不同的是,auto_ptr的复制语义会引起资源对象控制权转移的问题。
#include <iostream>
#include <memory>
using namespace std;
class Test
{
private:
string s;
public:
Test(string s):s(s)
{
cout << s << "构造函数" << endl;
}
~Test()
{
cout << s << "析构函数" << endl;
}
void show()
{
cout << s << "执行程序" << endl;
}
};int main()
{
{
Test *t1 = new Test("A");
// 创建一个智能指针管理t1
auto_ptr<Test> ap1(t1); // ap1 管理t1
auto_ptr<Test> ap2(ap1); // 显式调用拷贝构造函数
cout << ap1.get() << " " << ap2.get() << endl; // 0 0x1052780
auto_ptr<Test> ap3 = ap2; // 隐式调用构造函数
// 0 0 0xe82780
cout << ap1.get() << " " << ap2.get() << " " << ap3.get() << endl;
auto_ptr<Test> ap4;
ap4 = ap3; // 赋值运算符
// 0 0 0 0x922780
cout << ap1.get() << " " << ap2.get() <<
" " << ap3.get() << " " << ap4.get() << endl; }
return 0;
} 3、unique_ptr
作为对auto_ptr的改进,unique_ptr对其他持有的资源对象具有唯一控制权,即不可以通过常规的复制语义转移或拷贝资源对象的控制权。

通过特殊的语法实现控制权的转移效果。
#include <iostream>
#include <memory>using namespace std;class Test
{
private:string s;
public:Test(string s):s(s){
cout << s << "构造函数" << endl;}~Test(){
cout << s << "析构函数" << endl;}void show(){
cout << s << "执行程序" << endl;}
};int main()
{{
Test *t1 = new Test("A");// 创建一个智能指针管理t1unique_ptr<Test> up1(t1); // up1 管理t1unique_ptr<Test> up2(move(up1)); // 显式调用拷贝构造函数
cout << up1.get() << " " << up2.get() << endl; // 0 0x1052780unique_ptr<Test> up3 = move(up2); // 隐式调用构造函数// 0 0 0xe82780
cout << up1.get() << " " << up2.get() << " " << up3.get() << endl;unique_ptr<Test> up4;
up4 = move(up3); // 赋值运算符// 0 0 0 0x922780
cout << up1.get() << " " << up2.get() <<" " << up3.get() << " " << up4.get() << endl;}return 0;
} 
4、shared_ptr
unique_ptr对资源具有独占性,多个shared_ptr对象可以共享资源。
shared_ptr有两种创建方式:

两种创建方式的区别在于后者是一步到位(创建资源对象+关系绑定),前者分为两步完成(先创建资源对象,再进行关系绑定)。
新方式的优点:
- 安全性更好
- 性能更好
新方式的缺点:
- 资源释放效率低
每多一个shared_ptr对资源进行管理,引用计数将+1,每个指向该对象的shared_ptr对象销毁时,引用计数-1,最后一个shared_ptr对象销毁时,计数清零,资源对象销毁。
#include <iostream>
#include <memory>
using namespace std;
class Test
{
private:string s;
public:Test(string s):s(s){
cout << s << "构造函数" << endl;}~Test(){
cout << s << "析构函数" << endl;}void show(){
cout << s << "执行程序" << endl;}
};
int main()
{shared_ptr<Test> sp3;{shared_ptr<Test> sp1 = make_shared<Test>("A");
cout << "引用计数:" << sp1.use_count() << endl;shared_ptr<Test> sp2(sp1); // 拷贝构造函数
cout << "引用计数:" << sp2.use_count() << endl; sp3 = sp2;
cout << "引用计数:" << sp3.use_count() << endl;}
cout << "引用计数:" << sp3.use_count() << endl;return 0;
} 
5、weak_ptr
weak_ptr是一个不控制资源对象的智能指针,也不会影响资源的引用计数,其主要目的是协助shared_ptr工作。
通过weak_ptr的构造函数,参数传入一个持有资源对象的shared_ptr对象或者weak_ptr对象即可创建。
weak_ptr与资源对象呈现弱相关性,所以不支持get等函数直接操作资源对象。
建议weak_ptr调用lock函数之前,先检测引用计数是否大于0,或使用expried()函数检测是否可以转换为shared_ptr。
lock()函数,通过传入持有资源对象的对象创建新对象
#include <iostream>
#include <memory>
using namespace std;
class Test
{
private:string s;
public:Test(string s):s(s){
cout << s << "构造函数" << endl;}~Test(){
cout << s << "析构函数" << endl;}void show(){
cout << s << "执行程序" << endl;}
};
int main()
{weak_ptr<Test> wp3;{shared_ptr<Test> sp1 = make_shared<Test>("A");weak_ptr<Test> wp1 = sp1;
cout << sp1.use_count() << endl; // 1
cout << wp1.use_count() << endl; // 1weak_ptr<Test> wp2(wp1); // 拷贝构造
cout << wp2.use_count() << endl;shared_ptr<Test> sp2 = wp1.lock();
cout << sp2.use_count() << endl; // 2 wp3 = wp2;
cout << wp3.use_count() << endl;}
cout << wp3.use_count() << endl; // 0if(wp3.expired()){
cout << "无法使用lock函数,因为没有可以管理的对象" << endl;}return 0;
}

相关文章:
c++-智能指针
1、概念 堆内存的对象需要手动使用delete销毁,如果忘记使用delete销毁就会造成内存泄漏。 所以C在ISO 98标注中引入了智能指针的概念,并在C11 中趋于完善。 使用智能指针可以让堆内存对象具有栈内存对象的特性。原理时给需要自动回收的堆内存对象套上一层…...
烟花燃放如何管控?智能分析网关V4烟火检测保障烟火安全
一、方案背景 随着元旦佳节的热潮退去,春节也即将来临,在众多传统的中国节日里,烟花与烧纸祭祀都是必不可少的,一方面表达了人们对节日的庆祝的期许,另一方面也是一种对故者思念的寄托。烟花爆竹的燃放不仅存在着巨大的…...
Vue实现版本号输入、删除时光标自动移动到上、下一个输入框前端demo
前言 首先声明,我平时的工作主要是后端JAVA开发,该demo为前端练习,记录一下劳动成果,希望对大家有所帮助,如果有写的不妥的地方,欢迎大家指正,一起学习、共同进步。 背景 手机验证码、银行卡…...
【胖虎的逆向之路】Android自制Https证书实现双向认证
Android自制Https证书实现双向认证 1.基本概念1.1 HTTP1.2 HTTPS1.3 加密方式1.3.1 对称加密1.3.2 非对称加密 1.4 SSL 功能1.4.1 客户对服务器的身份认证1.4.2 服务器对客户的身份认证1.4.3 建立服务器与客户之间安全的数据通道 1.5 CA 证书 2.证书生成2.1 生成根证书…...
解析千兆多模光模块SFP-GE-SX
千兆多模光模块是一种基于光纤通信的光电转换模块,具有千兆(Gigabit)级别的传输速率。本文将对千兆多模光模块的定义、传输距离、参数、及其应用领域等进行详细介绍。 一、千兆多模光模块SFP-GE-SX是什么? 千兆多模光模块SFP-GE-S…...
Go语言基础简单了解
文章目录 前言关于Go学习流程 基础语法注释变量常量数据类型运算符fmt库 流程控制if、switch、selectfor、break、continue遍历String 函数值传递和引用传递deferinit匿名、回调、闭包函数 数组和切片Map结构体自定义数据类型接口协程和channel线程锁异常处理泛型文件读取文件写…...
kafka重平衡经验总结
文章目录 概要背景解决方法技术细节小结 概要 关于kafka重平衡问题在实践工作的应用 背景 重平衡包括以下几种场景: 消费者组内成员发生变更,这个变更包括了增加和减少消费者。注意这里的减少有很大的可能是被动的,就是某个消费者崩溃退出了主题的分…...
Py之jupyter_client:jupyter_client的简介、安装、使用方法之详细攻略
Py之jupyter_client:jupyter_client的简介、安装、使用方法之详细攻略 目录 jupyter_client的简介 jupyter_client的安装 jupyter_client的使用方法 1、基础用法 (1)、获取内核信息 (2)、执行代码块 (3)、远程执行代码 jupyter_client的简介 jupyter_client 包含 Jupyter 协…...
61.网游逆向分析与插件开发-游戏增加自动化助手接口-游戏红字公告功能的逆向分析
内容来源于:易道云信息技术研究院VIP课 上一节内容:游戏公告功能的逆向分析与测试-CSDN博客 码云地址(master分支):https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号:63e04cc40f649d10ba2f4f…...
neo4j查询语言Cypher详解(五)--apoc
APOC (Awesome Procedures on Cypher)是一个Neo4j库,它提供了对其他过程和函数的访问,扩展了Cypher查询语言的使用。 apoc MATCH (n:Movie) CALL apoc.create.addLabels( n, [ n.genre ] ) YIELD node REMOVE node.genre RETURN node;附录 参考 apoc…...
odoo17 | 视图操作按钮
前言 到目前为止,我们主要通过声明字段和视图来构建我们的模块。在上一章中,我们刚刚通过计算字段和onchanges引入了业务逻辑。在任何真实的业务场景中,我们都会希望将一些业务逻辑链接到操作按钮。在我们的房地产示例中,我们希望…...
KBDPL.DLL文件丢失,软件游戏无法启动,修复方法
不少小伙伴,求助说遇到Windows弹窗提示“KBDPL.DLL文件丢失,应用无法启动的问题”,不知道应该怎么修复? 首先,先来了解“KBDPL.DLL文件”是什么? kbdpl.dll是Windows操作系统的一部分,是一个动…...
Webpack5 常用优化总结
本文主要总结经常用到的一些代码性能优化、减小代码体积、提升webpack打包构建速度等内容的方法。具体的实现可参考webpack官网查看相关示例。 注:如果读者还未接触过webpack,请先了解webpack的基本使用。 正文: SourceMap ---- 提升开发体…...
Oracle-视图与索引
视图 简介 视图是一种虚表 视图建立在已有表的基础上,视图赖以建立的的这些表成为基表 向视图提供的数据的内容的语句的select 语句,可以将视图理解为存储起来的select 语句 视图向用户提供基表数据的另外一种表现形式 视图的好处 控制数据访问 …...
在Linux写自己的第一个程序“hello Linux”
01.nano指令 我们在Windows中有很多的编译环境,大家应该都很熟悉,但是在Linux中,我们怎么写代码呢? 这里,我介绍一个非常简单的指令->nano 这个指令就类似于我们Windows中的记事本,使用方法也很简单 …...
【AI视野·今日Robot 机器人论文速览 第六十八期】Tue, 2 Jan 2024
AI视野今日CS.Robotics 机器人学论文速览 Tue, 2 Jan 2024 Totally 12 papers 👉上期速览✈更多精彩请移步主页 Daily Robotics Papers Edge Computing based Human-Robot Cognitive Fusion: A Medical Case Study in the Autism Spectrum Disorder Therapy Author…...
图像识别快速实现
文本的跑通了,接下来玩玩图片场景 1. 引入模型 再另起类test_qdrant_img.py,转化图片用到的模型和文本不太一样,我们这里使用ResNet-50模型 import unittest from qdrant_client.http.models import Distance, VectorParams from qdrant_cl…...
一文详解动态 Schema
在数据库中,Schema 常有,而动态 Schema 不常有。 例如,SQL 数据库有预定义的 Schema,但这些 Schema 通常都不能修改,用户只有在创建时才能定义 Schema。Schema 的作用是告诉数据库使用者所希望的表结构,确保…...
Web网页开发-总结笔记2
28.为什么会出现浮动?浮动会带来哪些问题? 1)为什么会出现浮动: 为了页面排版时块元素同行显示 2)浮动带来的问题: 父元素高度崩塌29.清除浮动的方法 (额外标签法、父级overflow、after伪元素、双伪元素) (…...
C#的StringBuilder方法
一、StringBuilder方法 StringBuilder方法Append()向此实例追加指定对象的字符串表示形式。AppendFormat()向此实例追加通过处理复合格式字符串(包含零个或更多格式项)而返回的字符串。 每个格式项都由相应的对象自变量的字符串表示形式替换。AppendJoi…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
今日科技热点速览
🔥 今日科技热点速览 🎮 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售,主打更强图形性能与沉浸式体验,支持多模态交互,受到全球玩家热捧 。 🤖 人工智能持续突破 DeepSeek-R1&…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
MySQL 知识小结(一)
一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库,分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷,但是文件存放起来数据比较冗余,用二进制能够更好管理咱们M…...
给网站添加live2d看板娘
给网站添加live2d看板娘 参考文献: stevenjoezhang/live2d-widget: 把萌萌哒的看板娘抱回家 (ノ≧∇≦)ノ | Live2D widget for web platformEikanya/Live2d-model: Live2d model collectionzenghongtu/live2d-model-assets 前言 网站环境如下,文章也主…...
LOOI机器人的技术实现解析:从手势识别到边缘检测
LOOI机器人作为一款创新的AI硬件产品,通过将智能手机转变为具有情感交互能力的桌面机器人,展示了前沿AI技术与传统硬件设计的完美结合。作为AI与玩具领域的专家,我将全面解析LOOI的技术实现架构,特别是其手势识别、物体识别和环境…...
【51单片机】4. 模块化编程与LCD1602Debug
1. 什么是模块化编程 传统编程会将所有函数放在main.c中,如果使用的模块多,一个文件内会有很多代码,不利于组织和管理 模块化编程则是将各个模块的代码放在不同的.c文件里,在.h文件里提供外部可调用函数声明,其他.c文…...
Win系统权限提升篇UAC绕过DLL劫持未引号路径可控服务全检项目
应用场景: 1、常规某个机器被钓鱼后门攻击后,我们需要做更高权限操作或权限维持等。 2、内网域中某个机器被钓鱼后门攻击后,我们需要对后续内网域做安全测试。 #Win10&11-BypassUAC自动提权-MSF&UACME 为了远程执行目标的exe或者b…...
