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…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
mac 安装homebrew (nvm 及git)
mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用: 方法一:使用 Homebrew 安装 Git(推荐) 步骤如下:打开终端(Terminal.app) 1.安装 Homebrew…...
【C++进阶篇】智能指针
C内存管理终极指南:智能指针从入门到源码剖析 一. 智能指针1.1 auto_ptr1.2 unique_ptr1.3 shared_ptr1.4 make_shared 二. 原理三. shared_ptr循环引用问题三. 线程安全问题四. 内存泄漏4.1 什么是内存泄漏4.2 危害4.3 避免内存泄漏 五. 最后 一. 智能指针 智能指…...
