智能指针解读(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…...
从RS485到TCP/IP:Modbus协议V1.1b3的三种组网方式对比(含WireShark抓包分析)
从RS485到TCP/IP:Modbus协议V1.1b3的三种组网方式深度实战解析 在工业自动化领域,Modbus协议已经服役超过40年,却依然保持着惊人的生命力。作为工程师,我们常常面临一个关键抉择:在RS485、Modbus和TCP/IP这三种主流组…...
三步掌握Dark Reader:从入门到精通的护眼浏览解决方案
三步掌握Dark Reader:从入门到精通的护眼浏览解决方案 【免费下载链接】darkreader Dark Reader Chrome and Firefox extension 项目地址: https://gitcode.com/gh_mirrors/da/darkreader Dark Reader是一款能够为任何网站启用深色模式的浏览器扩展ÿ…...
WarcraftHelper:魔兽争霸3终极优化指南 - 解锁现代硬件性能
WarcraftHelper:魔兽争霸3终极优化指南 - 解锁现代硬件性能 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper WarcraftHelper是一款专为魔兽…...
从零搭建SRS流媒体服务器:实现RTMP推拉流的实战部署指南
1. 为什么选择SRS搭建流媒体服务器? 最近几年直播和实时视频的需求爆发式增长,很多开发者都在寻找轻量高效的流媒体服务器方案。我测试过不少开源方案,最终发现SRS(Simple Realtime Server)是最适合个人和小团队自建的…...
你还在给每个图片父元素加类名?CSS :has() 让选择器“逆天改命”
你还在给每个图片父元素加类名?CSS :has() 让选择器“逆天改命” 引言 “组长,这个需求我写不了。” “什么需求?” “产品经理说,所有包含图片的卡片,要在卡片上加一个‘带图标识’的边框。但是这些卡片是动态渲染的&…...
Path of Building:流放之路玩家必备的终极Build规划神器
Path of Building:流放之路玩家必备的终极Build规划神器 【免费下载链接】PathOfBuilding Offline build planner for Path of Exile. 项目地址: https://gitcode.com/GitHub_Trending/pa/PathOfBuilding 如果你正在玩《流放之路》并为复杂的Build规划感到头…...
Pandoc:5步掌握全能文档转换的极简工作流
Pandoc:5步掌握全能文档转换的极简工作流 【免费下载链接】pandoc Universal markup converter 项目地址: https://gitcode.com/gh_mirrors/pa/pandoc 价值定位:为什么每个开发者都需要一款"格式翻译官" 当你需要将Markdown笔记转换为…...
算法基础篇(11)Floyd算法
Floyd算法本质是动态规划,用来求任意两点之间的最短路,也称为插点法。通过不断在两点之间加入新的点来更新最短路。1、状态表示:f[k][i][j]表示:仅仅经过1~k这些点,结点i走到结点j的最短路径的长度。2、状态转移方程&a…...
Realtek RTL8125 2.5GbE网卡驱动技术指南
Realtek RTL8125 2.5GbE网卡驱动技术指南 【免费下载链接】realtek-r8125-dkms A DKMS package for easy use of Realtek r8125 driver, which supports 2.5 GbE. 项目地址: https://gitcode.com/gh_mirrors/re/realtek-r8125-dkms 1. 问题诊断:网络设备识别…...
SVM支持向量机核函数选择避坑指南:从线性到RBF,如何根据你的数据特征做决定?
SVM核函数选择实战指南:从数据特征到模型调优的全流程解析 第一次在Scikit-learn中调用SVC类时,面对kernel参数下拉菜单里linear、poly、rbf、sigmoid四个选项,我盯着屏幕发了五分钟呆——这感觉就像走进一家高级餐厅,服务员递来一…...
