智能指针解读(2)
前面一篇文章,我讲解了智能指针的原理,并实现了一个简单的智能指针。为了加深对智能指针的理解,在这篇文章中,我把C++中的几个智能指针讲解下:auto_ptr, unique_ptr, shared_ptr, weak_ptr。
1、auto_ptr
前面的文章我们把smart_ptr的拷贝构造函数、赋值运算符都禁掉了。auto_ptr在拷贝构造函数和赋值运算符里是怎么处理的呢?它会把原来的指针赋为nullptr。
template<class T>
class auto_ptr {
public:auto_ptr(T* _ptr) : ptr(_ptr) {}auto_ptr(auto_ptr& _ap) : ptr(_ap.ptr) {_ap.ptr = nullptr;}auto_ptr<T>& operator = (auto_ptr<T>& _ap) {if (ptr != _ap.ptr) {ptr = _ap.ptr;_ap.ptr = nullptr;}return *this;}~auto_ptr() {delete ptr;ptr = nullptr;}T& operator * () {return *ptr;}T* operator -> () {return ptr;}
private:T* ptr;
};
3、unique_ptr
unique_ptr是c++11版本库中提供的智能指针,它直接将拷贝构造函数和赋值重载函数给禁用掉。所以unique_ptr只能move,不能赋值。
4、shared_ptr
shared_ptr允许多个智能指针可以指向同一块资源,并且能够保证共享的资源只会被释放一次。
shared_ptr采用的是引用计数原理来实现多个shared_ptr对象之间共享资源:
(1)引用计数用来记录该资源被几个对象共享。
(2)当一个shared_ptr对象被销毁时(调用析构函数),析构函数内就会将该计数减1。
(3)如果引用计数减为0后,则表示自己是最后一个使用该资源的shared_ptr对象,必须释放资源。
(4)如果引用计数不是0,就说明自己还有其他对象在使用,则不能释放该资源。
在使用shared_ptr时,要注意不要让2个shared_ptr指向同一个原始指针,比如:
A* p = new A(10);
shared_ptr<A> sp1(p), sp2(p);
sp1 和 sp2 并不会共享同一个对 p 的引用计数,而是各自将对 p 的引用计数都记为 1(sp2 无法知道 p 已经被 sp1 托管过)。这样,当 sp1 消亡时要析构 p,sp2 消亡时要再次析构 p,这会导致程序崩溃。
5、weak_ptr
weak_ptr类的对象可以指向shared_ptr,但不会改变shared_ptr的引用计数。一旦最后一个shared_ptr被销毁时,对象就会被释放。
weak_ptr并没有重载operator->和operator *操作符,因此不可直接通过weak_ptr使用对象,典型的用法是调用其lock函数来获得shared_ptr示例,进而访问原始对象。
我们来看一个shared_ptr交叉引用的例子:
class B;
class A
{
public:shared_ptr<B> sp;~A(){cout << "~A"<<endl;}
};
class B
{
public:shared_ptr<A> sp;~B(){cout << "~B"<<endl;}
};void fun() {shared_ptr<B> pb(new B());shared_ptr<A> pa(new A());pb->sp = pa;cout << "pb.use_count " << pb.use_count() << endl;//1cout << "pa.use_count " << pa.use_count() << endl;//2pa->sp = pb;cout << "pb.use_count " << pb.use_count() << endl;//2cout << "pa.use_count " << pa.use_count() << endl;//2//并没有输出 ~A, ~B,也就是class B;
class A
{
public:shared_ptr<B> sp;~A(){cout << "~A"<<endl;}
};
class B
{
public:shared_ptr<A> sp;~B(){cout << "~B"<<endl;}
};void fun() {shared_ptr<B> pb(new B());shared_ptr<A> pa(new A());pb->sp = pa;cout << "pb.use_count " << pb.use_count() << endl;//1cout << "pa.use_count " << pa.use_count() << endl;//2pa->sp = pb;cout << "pb.use_count " << pb.use_count() << endl;//2cout << "pa.use_count " << pa.use_count() << endl;//2//没有输出~A, ~B。也就是没有调用A和B的析构函数。
}
怎么去避免这种交叉引用呢?这就需要使用weak_ptr:把A中的shared_ptr<B> sp改为weak_ptr<B> sp_weak,这样传递时不会增加sp引用计数use_count()的值,所以最终能够使A、B资源正常释放:
class B;
class A
{
public://shared_ptr<B> sp;weak_ptr<B> sp_weak;~A(){cout << "~A"<<endl;}
};
class B
{
public:shared_ptr<A> sp;~B(){cout << "~B"<<endl;}
};void fun() {shared_ptr<B> pb(new B());shared_ptr<A> pa(new A());pb->sp = pa;cout << "pb.use_count " << pb.use_count() << endl;//1cout << "pa.use_count " << pa.use_count() << endl;//2//pa->sp = pb;pa->sp_weak = pb;cout << "pb.use_count " << pb.use_count() << endl;//1cout << "pa.use_count " << pa.use_count() << endl;//2shared_ptr<B> pa2 = pa->sp_weak.lock();}
相关文章:

智能指针解读(2)
前面一篇文章,我讲解了智能指针的原理,并实现了一个简单的智能指针。为了加深对智能指针的理解,在这篇文章中,我把C中的几个智能指针讲解下:auto_ptr, unique_ptr, shared_ptr, weak_ptr。 1、auto_ptr 前面的文章我…...
javax.servlet.ServletException: 非法访问资源(/j_spring_security_check)
部署的web页面登录访问报错500状态码。 开发出于安全考虑引入了refer白名单,但是没有通知交付人员。 需要将浏览器访问的url加入到refer白名单中,问题解决。 filterconfig.xml <refer-domain> <value>http://localhost</value> …...
自定义事件的使用
绑定自定义事件 在Vue.js中,你可以使用自定义事件来实现组件之间的通信。自定义事件允许你在一个组件中触发事件,并在另一个组件中监听并响应该事件。以下是自定义事件的使用方法: 定义一个触发事件的组件: <template>&l…...

buuctf-[ASIS 2019] Unicorn shop
打开网站 先去看看源代码8 前面一大坨绿的,肯定是提示,都是英文有点无语 试了试打开admin.password看看有没有东西 nice毫无变化 然后我就看了看这个页面,其实就是购买这四个商品 but当我购买第一个商品时 回显 意思就是只能输入一个字…...

72.Linux系统下printf函数的输出问题
目录 printf函数输出问题 为啥要放到缓冲区呢? \n 强制刷新缓冲区 fflush 强制刷新缓冲区 printf函数输出问题 在 Linux 下,printf 函数通常会先将输出放入缓冲区而不是立即将其发送到终端或文件。这是为了提高性能,因为逐个字符或逐个…...

Ubuntu20.4搭建基于iRedMail的邮件服务器
iRedMail 是一个基于 Linux/BSD 系统的零成本、功能完备、成熟的邮件服务器解决方案。基于ubuntu20.4搭建基于iRedMail的邮件服务器包括环境配置,iRedMail安装与配置,iRedMail调整邮件附件大小等3个小节进行描述。具体如下详细描述。 1 环境配置 1.设置…...
大数据-Spark-Spark开发高频面试题
一、spark的内存分布 堆内内存:在这使用堆内内存的时候,如果我们设置了堆内内存2个g的话,读取的数据也是两个g,此时又来两个g的数据,这样就会产生OOM溢出,因为处理完两个g的数据,并不会马上进行…...

云原生容器平台——新华资产数字化转型加速器
新华资产管理股份有限公司(以下简称“新华资产”)于2006年5月经中国保险监督管理委员会批准、7月3日正式挂牌成立,是国内首批专业保险资产管理机构。2020年上半年,公司管理的资产规模突破万亿元人民币,投资收益水平居行…...

ubuntu 22.04运行opencv4的c++程序遇到的问题
摘要:本文介绍一下在ubuntu系统中,运行一个最简单的opencv4程序都出问题的解决方法,并对其基本原理作简单阐述。解决问题的方法有很多,本文只提供其中一种。 opencv版本是4.2.0,ubuntu版本是20.04 查询opencv版本的指…...

MDPI模板报错的问题---提示缺少sty文件
MDPI模板报错的问题—提示缺少sty文件 平时大多数提交IEEE trans模板时大多使用CTEX编译,然而,MDPI模板需要用texlive,二者之间如果先安装CTEX后安装texlive将会导致库文件的冲突。结果将会报缺少sty的文件错。网上提供了很多解决方案&#…...

【教程】微信小程序导入外部字体详细流程
前言 在微信小程序中,我们在wxss文件中通过font-family这一CSS属性来设置文本的字体,并且微信小程序有自身支持的内置字体,可以通过代码提示查看微信小程序支持字体: 这些字体具体是什么样式可以参考: 微信小程序--字…...

关于Kali部署OneForAll,不能运行问题
问题描述 运行OneForAll后,出现了如下报错 问题: importterror:无法从’re’导入名称’sre_parse’ (/usr/lib/python3.11/re/init.py) Traceback (most recent call last):File "/home/kali/桌面/App/OneForAll/oneforall.py", line 16, in…...

vue3中使用el-upload + tui-image-editor进行图片处理
效果如下 看之前请先看上一篇《vue3中使用组件tui-image-editor进行图片处理》中的 1、第一步安装 2、第二部封装组件 本篇只是在这基础上结合el-upload使用组件 3、第三步结合el-upload使用组件 <template><el-dialog:title"dialogTitle":modelValue&qu…...

二叉树顺序结构及实现
👉二叉树顺序结构及实现 1.二叉树的顺序结构2.堆的概念及结构3.堆的实现3.1堆向下调整算法3.2堆向上调整算法 4.堆的创建4.1堆创建方法14.1.1构建堆结构体4.1.2堆的初始化4.1.3堆数据添加向上调整4.1.4主函数内容 4.2堆的创建方法24.2.1堆数据添加向下调整 4.3堆数据…...
python读取influxdb中数据
示例代码一:从infludb中获取指定时间段time和value值,并作图保存 from influxdb_client import InfluxDBClient import matplotlib.pyplot as plt# InfluxDB连接信息 url "http://localhost:8086" token "your_token" org "…...

【网络编程】UDP Socket编程
UDP Socket编程 一. DatagramSocket二. DatagramPacket三. InetSocketAddress四. 执行流程五. 代码示例: UDP 回显服务器 数据报套接字: 使用传输层 UDP 协议 UDP: 即 User Datagram Protocol(用户数据报协议),传输层协议。 UDP…...
[GIT]版本控制工具
[GIT]版本控制工具 Git 的命令Git 的配置信息查看现有 Git 配置信息设置 Git 配置信息用户信息配置文本编辑器配置差异分析工具配置 编辑 Git 配置文件 Git 仓库操作初始化 Git 仓库克隆 Git 仓库Git 分支仓库创建Git 远程仓库命令 Git 提交历史Git 标签添加标签查看已有标签删…...

Linux文件管理命令
Linux命令行 命令空格参数(可写可不写)空格文件(可写可不写)ls/opt 根目录下的opt文件夹ls-a 显示所有文件及隐藏文件/optls -l 详细输出文件夹内容 ls -h 输出文件大小(MB...)ls--full-time 完整时间格式输出ls-d 显示文件夹本身信息,不输出内容ls-t 根据最后修改…...
Netty面试题(三)
文章目录 前言一、如何选择序列化协议?二、Netty 的零拷贝实现?总结 前言 如何选择序列化协议?Netty 的零拷贝实现? 一、如何选择序列化协议? 具体场景 对于公司间的系统调用,如果性能要求在 100ms 以上的…...

risc-v dv源代码分析
地址为 GitHub - chipsalliance/riscv-dv: Random instruction generator for RISC-V processor verificationRandom instruction generator for RISC-V processor verification - GitHub - chipsalliance/riscv-dv: Random instruction generator for RISC-V processor verif…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...

【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?
uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件,用于在原生应用中加载 HTML 页面: 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...

莫兰迪高级灰总结计划简约商务通用PPT模版
莫兰迪高级灰总结计划简约商务通用PPT模版,莫兰迪调色板清新简约工作汇报PPT模版,莫兰迪时尚风极简设计PPT模版,大学生毕业论文答辩PPT模版,莫兰迪配色总结计划简约商务通用PPT模版,莫兰迪商务汇报PPT模版,…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

windows系统MySQL安装文档
概览:本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容,为学习者提供全面的操作指导。关键要点包括: 解压 :下载完成后解压压缩包,得到MySQL 8.…...