弱引用与C++智能指针

笔试题遇到了弱引用,但是C++标准库是没有这个概念的,学了智能指针但是没有听说过弱引用,因此总结一下两者
学习视频链接来自B站

https://www.bilibili.com/video/BV1gV4y1G7fH?p=2&vd_source=fa4ef8f26ae084f9b5f70a5f87e9e41b

智能指针

C++的对象本质上都需要调用delete来释放,当代码多起来时,总会有忘记手动delete的时候。因此C++提供了智能指针方便程序员。

unique_ptr

使用前需要导入memory头文件,unique_ptr只能单独管理一个对象,因此它的拷贝构造和=运算符被禁用,所以也不能进行值传递,nullptr也重载解引用运算,可以像普通指针一样通过*来访问

#include <iostream>
#include <memory>
using namespace std;
class A {
public:string m_Name;A() { cout << "这是A类的默认构造函数" << endl; }A(string name){this->m_Name = name;cout << "这是A类的有参构造函数" << endl;}~A(){cout << "string  = " << m_Name << "这是A类的析构函数" << endl;}
};int main()
{A* p = new A("Tom");//unique_ptr指针管理普通指针,unique_ptr指针本身也有自己的地址,第一种初始化方法unique_ptr<A> uPtr1(p);//推荐使用这种方法初始化一个智能指针unique_ptr<A> uPtr2(new A("Jerry"));//C++14语法unique_ptr<A> uPtr3 = make_unique<A>("Jack");return 0;
}

在这里插入图片描述
注:unique_ptr编译器上做了特殊的处理
1.将一个临时的unique_ptr赋值给另一个时(局部变量),编译器是允许这么做的;若unique_ptr已经管理了一个指针,那么它会先释放原本管理的指针,再去管理这个临时的unique_ptr,若这个变量长期存在(全局变量),那么这个操作是不允许的。原本的重载运算符=已经被禁用了,依然能接受赋值操作,非常神奇
**2.用nullptr给unique_ptr赋值将对象释放,空的unique_ptr == nullptr **
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
第九点贴图
在这里插入图片描述

shared_ptr

大体上与前一种智能指针一致,但是一个是独享,一个是共享,因此没有禁用拷贝构造和重载=
共享不是赋值,shared_ptr管理的原始指针只有一份
在这里插入图片描述
特别注意
指向资源的引用计数多一个,计数值就 + 1,指向资源的引用计数少一个,计数值就 - 1
在这里插入图片描述
3 4同unique_ptr
在这里插入图片描述
注意:
unique_ptr可以转换为shared_ptr,但是反过来不行
在这里插入图片描述
在这里插入图片描述

#include <iostream>
#include <memory>
using namespace std;
class A {
public:string m_Name;A() { cout << "这是A类的默认构造函数" << endl; }A(string name){this->m_Name = name;cout << "这是A类的有参构造函数" << endl;}~A(){cout << "string  = " << m_Name << "这是A类的析构函数" << endl;}
};
void test01()
{A* p = new A("Tom");//unique_ptr指针管理普通指针,unique_ptr指针本身也有自己的地址,第一种初始化方法unique_ptr<A> uPtr1(p);//推荐使用这种方法初始化一个智能指针unique_ptr<A> uPtr2(new A("Jerry"));//C++14语法unique_ptr<A> uPtr3 = make_unique<A>("Jack");cout << "解引用运算符返回对象的属性," << "A类的名字为:" << (*uPtr2).m_Name << endl;cout << "get方法返回管理的裸指针," << "A类的名字为:" << uPtr2.get()->m_Name << endl;
}
void test02()
{A* p = new A("Tom");//shared_ptr推荐使用这种方式初始化shared_ptr<A> sPtr = make_shared<A>("Jack");cout << "解引用运算符返回对象的属性," << "A类的名字为:" << (*sPtr).m_Name << endl;cout << "shared_ptr的引用计数为:" << sPtr.use_count() << endl; //shared_ptr可以使用这个API返回引用计数值,实际一般不关心具体的值
}int main()
{
//	test01();test02();return 0;
}

在这里插入图片描述

智能指针删除器

在这里插入图片描述

share_ptr自定义删除器

在这里插入图片描述

unique_ptr自定义删除器

较为麻烦
在这里插入图片描述

weak_ptr 与弱引用

弱引用概念

AI是这么解释的

"弱引用"在计算机科学中是一个概念,尤其在内存管理和垃圾收集(Garbage Collection)的上下文中。弱引用与强引用相对。当一个对象被强引用时,只要这个引用存在,垃圾收集器就不会回收这个对象。相反,当对象被弱引用时,垃圾收集器会忽略这个引用,并在适当的时候回收这个对象,即使这个弱引用还存在。

弱引用的主要目的是防止内存泄漏,尤其是在需要引用对象但又不想阻止其被垃圾收集器回收的情况下。例如,在缓存系统中,当缓存对象被弱引用时,如果缓存大小超过了限制,垃圾收集器可以回收这些对象,从而避免内存溢出。

更简单的说法
弱引用是一种特殊的引用类型,它允许你引用一个对象,但不会增加该对象的引用计数。这意味着弱引用不会“拥有”对象,也不会阻止对象被垃圾回收器回收。当对象被回收时,弱引用会自动失效,再次访问它会导致错误或异常。
弱引用的主要目的是解决循环引用的问题。在C++中,如果你有两个对象相互引用,即使它们在其他地方都没有被引用,它们也不会被垃圾回收器回收,因为它们相互引用形成了一个“环”。弱引用可以打破这个环,让垃圾回收器能够回收对象。

weak_ptr

没有重载运算符"->"和解引用运算符
在这里插入图片描述
如果对方没死,那么自己不能死,最后谁也没死成
在这里插入图片描述
例子如下

class A {
public:string m_Name;shared_ptr<B> p;A() { cout << "这是A类的默认构造函数" << endl; }A(string name){this->m_Name = name;cout << "这是A类的有参构造函数" << endl;}~A(){cout << "string  = " << m_Name << "这是A类的析构函数" << endl;}
};
class B {
public:string m_Name;shared_ptr<A> p;~B(){cout << "析构函数已经被调用" << endl;}
};
void test03()
{shared_ptr<A> pa = make_shared<A>();shared_ptr<B> pb = make_shared<B>();pa->p = pb;pb->p = pa;
}
int main()
{
//	test01();
//	test02();test03();return 0;
}

在这里插入图片描述
解决方法,将一个类的shared_ptr改成weak_ptr

#include <iostream>
#include <memory>
using namespace std;
class A;
class B {
public:string m_Name;weak_ptr<A> p;B(string name){this->m_Name = name;cout << "这是B类的有参构造函数" << endl;}~B(){cout << "B类的析构函数已经被调用" << endl;}
};
class A {
public:string m_Name;shared_ptr<B> p;A() { cout << "这是A类的默认构造函数" << endl; }A(string name){this->m_Name = name;cout << "这是A类的有参构造函数" << endl;}~A(){cout << "string  = " << m_Name << "这是A类的析构函数" << endl;}
};void test01()
{A* p = new A("Tom");//unique_ptr指针管理普通指针,unique_ptr指针本身也有自己的地址,第一种初始化方法unique_ptr<A> uPtr1(p);//推荐使用这种方法初始化一个智能指针unique_ptr<A> uPtr2(new A("Jerry"));//C++14语法unique_ptr<A> uPtr3 = make_unique<A>("Jack");cout << "解引用运算符返回对象的属性," << "A类的名字为:" << (*uPtr2).m_Name << endl;cout << "get方法返回管理的裸指针," << "A类的名字为:" << uPtr2.get()->m_Name << endl;
}
void test02()
{A* p = new A("Tom");//shared_ptr推荐使用这种方式初始化shared_ptr<A> sPtr = make_shared<A>("Jack");cout << "解引用运算符返回对象的属性," << "A类的名字为:" << (*sPtr).m_Name << endl;cout << "shared_ptr的引用计数为:" << sPtr.use_count() << endl; //shared_ptr可以使用这个API返回引用计数值,实际一般不关心具体的值
}
void test03()
{shared_ptr<A> pa = make_shared<A>("Jack");shared_ptr<B> pb = make_shared<B>("Tom");pa->p = pb;pb->p = pa;
}int main()
{
//	test01();
//	test02();test03();return 0;
}

在这里插入图片描述
在这里插入图片描述

关键,一般互相配合使用在多线程程序中
在这里插入图片描述
升级的同时加锁pa,pb都是weak_ptr,m_p未指向对方类型的shared_ptr
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2807581.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

C语言:指针的进阶讲解

目录 1. 二级指针 1.1 二级指针是什么&#xff1f; 1.2 二级指针的作用 2. 一维数组和二维数组的本质 3. 指针数组 4. 数组指针 5. 函数指针 6. typedef的使用 7. 函数指针数组 7.1 转移表 1. 二级指针 如果了解了一级指针&#xff0c;那二级指针也是可以很好的理解…

基于django的购物商城系统

摘要 本文介绍了基于Django框架开发的购物商城系统。随着电子商务的兴起&#xff0c;购物商城系统成为了许多企业和个人创业者的首选。Django作为一个高效、稳定且易于扩展的Python web框架&#xff0c;为开发者提供了便捷的开发环境和丰富的功能模块&#xff0c;使得开发购物商…

第三百六十五回

文章目录 1. 概念介绍2. 方法与信息2.1 获取方法2.2 详细信息 3. 示例代码4. 内容总结 我们在上一章回中介绍了"如何获取设备信息"相关的内容&#xff0c;本章回中将介绍如何获取App自身的信息.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 我们在本…

【mysql】1000w数据量的分页查询SQL,如何优化提升性能?

文章目录 优化场景特别注意&#xff01;&#xff01;&#xff01;有前提&#xff0c;谨慎使用 优化场景 当表数据量非常大时&#xff0c;需要进行分页查询如果慢的时候&#xff0c;可以考虑优化下。 假设一页展示10条&#xff0c;查询第10w条后面的数据时候变慢了… 优化思路&…

【Java程序设计】【C00284】基于Springboot的校园疫情防控管理系统(有论文)

基于Springboot的校园疫情防控管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的校园疫情防控系统 本系统分为系统功能模块、管理员功能模块以及学生功能模块。 系统功能模块&#xff1a;在系统首页可以查…

【Unity】双击C#脚本文件以单个文件打开(Visual Studio)、父类找不到、引用找不到、无法跳转等问题

问题&#xff1a;新安装一个Unity后&#xff0c;突然发现在工程里双击C#脚本&#xff0c;会一个一个打开&#xff0c;虽然也是用VS软件打开了&#xff0c;但是它无法被正确识别为Unity工程的C#脚本&#xff0c;也就是说所有命名空间无效&#xff0c;因为没关联上整个工程的解决…

【蓝牙协议栈】常见蓝牙分析工具介绍

目录 1. HCI 录制工具 2. Air log 工具 3. Vendor chip 工具 本文主要介绍调试蓝牙协议栈&#xff0c;定位蓝牙问题的工具&#xff0c;而不是常用的编译烧录工具等&#xff0c;也不是开发蓝牙芯片的工具&#xff01;本小节计划通过几个方面以及场景来介绍调试蓝牙的工具&…

【Vue3】‘vite‘ 不是内部或外部命令,也不是可运行的程序或批处理文件。

问题 今天拿到别人项目的时候&#xff0c;我平时比较习惯用pnpm&#xff0c;我就使用pnpm i先下载依赖包&#xff0c;下载完成后&#xff0c;启动项目&#xff0c;就开始报以下错误&#xff01; 但是当我执行pnpm i的时候&#xff0c;vite不应该就已经被我下载下来了吗 研究了…

【数据结构和算法初阶(C语言)】时间复杂度(衡量算法快慢的高端玩家,搭配例题详细剖析)

目录 1.算法效率 1.1如何衡量一个算法的好坏 1.2 算法的复杂度 2.主菜-时间复杂度 2.1 时间复杂度的概念 2.2 大O的渐进表示法 2.2.1算法的最好&#xff0c;最坏和平均的情况 3.经典时间复杂度计算举例 3.1计算冒泡排序的时间复杂度 3.2计算折半查找的时间复杂度 3.…

LLM权重量化

LLM权重量化 浮点表示的背景知识Nave 8位量化使用LLM.int8() 进行8位量化结论References 大型语言模型(llm)以其广泛的计算需求而闻名。通常&#xff0c;模型的大小是通过将**参数的数量(大小)乘以这些值的精度(数据类型)**来计算的。为了节省内存&#xff0c;可以通过称为量化…

Windows中的Git Bash运行conda命令:未找到命令的错误(已解决)

在windows中的Gitbash中 打开激活conda环境&#xff0c;并运行&#xff08;前提是你先安装好git&#xff08;自己去官网下载&#xff09;&#xff09;。 要能够在Gitbash上运行Conda&#xff0c; 临时配置 如果你只是临时用一下&#xff0c;就是临时爽一把&#xff0c;那就按…

【Linux】docker构建环境编译运行linux内核

文章目录 1. 使用docker构建linux内核编译运行环境1.1. 为普通用户安装docker并验证是否安装成功1.1.1. 安装docker稳定版1.1.2. 启动docker1.1.3. 将当前用户加入docker用户组1.1.4. 验证docker是否安装成功 1.2. docker基本使用1.2.1. 列出所有镜像1.2.2. 查看当前所有容器的…

C#之WPF学习之路(1)

目录 WPF的起源 C的qt和C#的wpf对比 winform 和 wpf有什么区别 安装 Visual Studio2022 创建 HelloWorld 程序 App.xaml与Application类 Application的生命周期 Window窗体的生命周期 WPF的起源 WPF&#xff08;Windows Presentation Foundation&#xff09;是一种用于…

基于SpringBoot的停车场管理系统

基于SpringBootVue的停车场管理系统的设计与实现~ 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringBootMyBatis工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 系统展示 前台首页 停车位 个人中心 管理员界面 摘要 摘要&#xff1a;随着城市化进程的…

ubantu设置mysql开机启动

阅读本文之前请参阅----MySQL 数据库安装教程详解&#xff08;linux系统和windows系统&#xff09; 在Ubuntu系统中设置MySQL开机启动&#xff0c;通常有以下几种方法&#xff1a; 1. **使用systemctl命令**&#xff1a; Ubuntu 16.04及更高版本使用systemd作为…

图像压缩感知的MATLAB实现(OMP)

前面实现了 压缩感知的图像仿真&#xff08;MATLAB源代码&#xff09; 效果还不错&#xff0c;缺点是速度慢如牛。 下面我们采用OMP对其进行优化&#xff0c;提升速度。具体代码如下&#xff1a; 仿真 构建了一个MATLAB文件&#xff0c;所有代码都在一个源文件里面&#xf…

【鸿蒙开发】第十四章 Stage模型应用组件-任务Mission

1 任务(Mission)管理场景 任务&#xff08;Mission&#xff09;管理相关的基本概念如下&#xff1a; AbilityRecord&#xff1a;系统服务侧管理一个UIAbility实例的最小单元&#xff0c;对应一个应用侧的UIAbility组件实例。系统服务侧管理UIAbility实例数量上限为512个。 Mi…

#FPGA(IRDA)

1.IDE:Quartus II 2.设备&#xff1a;Cyclone II EP2C8Q208C8N 3.实验&#xff1a;IRDA&#xff08;仿真接收一个来自0x57地址的数据0x22 (十进制34)&#xff09; 4.时序图&#xff1a; 5.步骤 6.代码&#xff1a; irda_receive.v module irda_receive ( input wire…

Llama2模型的优化版本:Llama-2-Onnx

Llama2模型的优化版本&#xff1a;Llama-2-Onnx。 Llama-2-Onnx是Llama2模型的优化版本。Llama2模型由一堆解码器层组成。每个解码器层&#xff08;或变换器块&#xff09;由一个自注意层和一个前馈多层感知器构成。与经典的变换器相比&#xff0c;Llama模型在前馈层中使用了不…

MySQL sql注意点

本文列取了常用但是容易遗漏的一些知识点。另外关键词一般大写&#xff0c;为了便于阅读所以很多小写。也为了给自己查缺补漏。 distinct&#xff08;去重&#xff09; 也许你经常对单个字段去重&#xff0c;并且知道不建议用distinct&#xff0c;而是group by&#xff0c;因为…