当前位置: 首页 > news >正文

智能指针解读(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)

前面一篇文章&#xff0c;我讲解了智能指针的原理&#xff0c;并实现了一个简单的智能指针。为了加深对智能指针的理解&#xff0c;在这篇文章中&#xff0c;我把C中的几个智能指针讲解下&#xff1a;auto_ptr, unique_ptr, shared_ptr, weak_ptr。 1、auto_ptr 前面的文章我…...

javax.servlet.ServletException: 非法访问资源(/j_spring_security_check)

部署的web页面登录访问报错500状态码。 开发出于安全考虑引入了refer白名单&#xff0c;但是没有通知交付人员。 需要将浏览器访问的url加入到refer白名单中&#xff0c;问题解决。 filterconfig.xml <refer-domain> <value>http://localhost</value> …...

自定义事件的使用

绑定自定义事件 在Vue.js中&#xff0c;你可以使用自定义事件来实现组件之间的通信。自定义事件允许你在一个组件中触发事件&#xff0c;并在另一个组件中监听并响应该事件。以下是自定义事件的使用方法&#xff1a; 定义一个触发事件的组件&#xff1a; <template>&l…...

buuctf-[ASIS 2019] Unicorn shop

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

72.Linux系统下printf函数的输出问题

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

Ubuntu20.4搭建基于iRedMail的邮件服务器

iRedMail 是一个基于 Linux/BSD 系统的零成本、功能完备、成熟的邮件服务器解决方案。基于ubuntu20.4搭建基于iRedMail的邮件服务器包括环境配置&#xff0c;iRedMail安装与配置&#xff0c;iRedMail调整邮件附件大小等3个小节进行描述。具体如下详细描述。 1 环境配置 1.设置…...

大数据-Spark-Spark开发高频面试题

一、spark的内存分布 堆内内存&#xff1a;在这使用堆内内存的时候&#xff0c;如果我们设置了堆内内存2个g的话&#xff0c;读取的数据也是两个g&#xff0c;此时又来两个g的数据&#xff0c;这样就会产生OOM溢出&#xff0c;因为处理完两个g的数据&#xff0c;并不会马上进行…...

云原生容器平台——新华资产数字化转型加速器

新华资产管理股份有限公司&#xff08;以下简称“新华资产”&#xff09;于2006年5月经中国保险监督管理委员会批准、7月3日正式挂牌成立&#xff0c;是国内首批专业保险资产管理机构。2020年上半年&#xff0c;公司管理的资产规模突破万亿元人民币&#xff0c;投资收益水平居行…...

ubuntu 22.04运行opencv4的c++程序遇到的问题

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

MDPI模板报错的问题---提示缺少sty文件

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

【教程】微信小程序导入外部字体详细流程

前言 在微信小程序中&#xff0c;我们在wxss文件中通过font-family这一CSS属性来设置文本的字体&#xff0c;并且微信小程序有自身支持的内置字体&#xff0c;可以通过代码提示查看微信小程序支持字体&#xff1a; 这些字体具体是什么样式可以参考&#xff1a; 微信小程序--字…...

关于Kali部署OneForAll,不能运行问题

问题描述 运行OneForAll后&#xff0c;出现了如下报错 问题&#xff1a; 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…...

二叉树顺序结构及实现

&#x1f449;二叉树顺序结构及实现 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中数据

示例代码一&#xff1a;从infludb中获取指定时间段time和value值&#xff0c;并作图保存 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 回显服务器 数据报套接字&#xff1a; 使用传输层 UDP 协议 UDP: 即 User Datagram Protocol&#xff08;用户数据报协议&#xff09;&#xff0c;传输层协议。 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 显示文件夹本身信息&#xff0c;不输出内容ls-t 根据最后修改…...

Netty面试题(三)

文章目录 前言一、如何选择序列化协议&#xff1f;二、Netty 的零拷贝实现&#xff1f;总结 前言 如何选择序列化协议&#xff1f;Netty 的零拷贝实现&#xff1f; 一、如何选择序列化协议&#xff1f; 具体场景 对于公司间的系统调用&#xff0c;如果性能要求在 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操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

在web-view 加载的本地及远程HTML中调用uniapp的API及网页和vue页面是如何通讯的?

uni-app 中 Web-view 与 Vue 页面的通讯机制详解 一、Web-view 简介 Web-view 是 uni-app 提供的一个重要组件&#xff0c;用于在原生应用中加载 HTML 页面&#xff1a; 支持加载本地 HTML 文件支持加载远程 HTML 页面实现 Web 与原生的双向通讯可用于嵌入第三方网页或 H5 应…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

莫兰迪高级灰总结计划简约商务通用PPT模版

莫兰迪高级灰总结计划简约商务通用PPT模版&#xff0c;莫兰迪调色板清新简约工作汇报PPT模版&#xff0c;莫兰迪时尚风极简设计PPT模版&#xff0c;大学生毕业论文答辩PPT模版&#xff0c;莫兰迪配色总结计划简约商务通用PPT模版&#xff0c;莫兰迪商务汇报PPT模版&#xff0c;…...

省略号和可变参数模板

本文主要介绍如何展开可变参数的参数包 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 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...

windows系统MySQL安装文档

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