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

【Rust中的智能指针】

Rust中的智能指针

  • 什么是智能指针?
  • 什么是Rust中的智能指针?
  • Rust中的智能指针Box
    • Box的使用场景
  • Rust中的智能指针Rc与Arc
  • rust中的RefCell
    • refcell的缺点:
    • rust中的weak
      • 先来看看C++中的weak_ptr定义
      • 代码示例:
    • Deref和Drop
  • 总结

什么是智能指针?

传统的指针,如C++中的裸指针,需要开发者自己申请和释放,如果开发者在使用过程中疏漏了回收,将会造成内存泄漏,在部署
实施时也会有oom的风险,智能指针即是为了解决这类问题而出现的,老生常谈的shared_ptr,unique_ptr,weak_ptr等,都是通过设计使得代码自动管理回收堆上的内存,提高代码的健壮性和方便性。


什么是Rust中的智能指针?

Rust由于其严格的安全性和所有权机制,除unsafe写法外,所有的堆内存都是通过语言特性管理的。其目的和其他语言一致都是为了健壮性和方便使用,与C++的智能指针使用的机制并无二致,都是使用了RAII(即资源获取即初始化),常见的rust智能指针有Box,Rc,Arc,Weak等。(个人理解:因为rust中的智能指针常与引用符号&结合使用,与其叫做智能指针,不如叫智能引用。)

Rust中的智能指针Box

首先看一下C++中的unique_ptr:
1.unique_ptr所指向(引用)的资源只能被unique_ptr所独占,不能被Copy,只能被转移。
2.自动析构不计数(结合一中的定义,独占型指针也没有任何计数的必要)
以上是unique_ptr的特点,这也是Rust中Box的主要特点:
只能转移所有权,不能Copy,同时只能有一个有效的Box。

Box的使用场景

由于Box的独占特点,其使用一般可以用在:

  1. 避免深拷贝一些多字节的数据
  2. 此文中提到的特征对象作为返回值使用,个人理解这是Box的最有用且最常用之处。
  3. 作为容器中得item如:
vec![Box<dyn Noise>] //比较适合在实践一些设计模式时使用

代码示例:

fn returns_noise(isdog: bool) -> Box<dyn Noise> {if isdog {Box::new(Dog {voice: String::from("wangwang",),})} else {Box::new(Cat {voice: String::from("miaomiao",),})}
}

Rust中的智能指针Rc与Arc

Rc: 全称 Reference Count,即引用计数。
Arc: 全称Atomic Reference Count,即原子性引用计数。

由定义可知,Arc对比与Rc的一大优点就是原子性,既线程安全。而实现了线程安全势必要损失了一些性能,所以Rc比Arc性能要更好些,这两个智能指针都是只读的
Rc与C++中的Shared_ptr机制类似,都是通过引用计数和RAII最终实现对于堆内存的自动控制,两者都是线程不安全的,最大的区别便是Rc只读
代码示例

{	let rc1 = Rc::new(String::from("hello world"));let rc2 = Rc::clone(&rc1);let rc3 = Rc::clone(&rc1);
}{	let mystr = String::from("hello world");let bx2 = Box::new(&mystr);let bx3 = Box::new(&mystr);//got error
}

以上是Rc与Box间的对比,由于所有权的转移bx3在二次借用时便会出错,而rc拥有计数规则,上述代码将通过编译。

这里细心的同学会留意到clone,这里只是浅拷贝。
原则上,栈上数据基本都可以直接复制,而堆上内存申请性能相对较慢,堆上内存非必要情况下不做深拷贝,同理,如果你作为一个语言开发者,非必要情况下也不会默认将堆上内存直接深拷贝。

Arc是Rc的线程安全版本,用法函数基本一致,不做代码示例,有需要可用自行查阅。

rust中的RefCell

在之前我们提到过Rc与C++中的shared_ptr很接近,但是是只读的,如何做到内部可变 —> 结合RefCell。

内部可变:在不改变外部套壳的情况下,可更改内部数值。

	let s = Rc::new(RefCell::new("hello ".to_string()));let s1 = s.clone();let s2 = s.clone();s2.borrom_mut().push_str("world");println!("{:?}",s);println!("{:?}",s1);println!("{:?}",s2);

均打印出 hello world

refcell的缺点:

代码使用了refcell后,rust被遵循的借用三大规则被移动到运行时,强制panic(也算比较安全,至少比unsafe从字面上的来看更舒服些)

rust中的weak

先来看看C++中的weak_ptr定义

std::weak_ptr is a smart pointer that holds a non-owning (“weak”) reference to an object that is managed by std::shared_ptr. It must be converted to std::shared_ptr in order to access the referenced object.
std::weak_ptr models temporary ownership: when an object needs to be accessed only if it exists, and it may be deleted at any time by someone else, std::weak_ptr is used to track the object, and it is converted to std::shared_ptr to acquire temporary ownership. If the original std::shared_ptr is destroyed at this time, the object’s lifetime is extended until the temporary std::shared_ptr is destroyed as well.
Another use for std::weak_ptr is to break reference cycles formed by objects managed by std::shared_ptr. If such cycle is orphaned (i.e., there are no outside shared pointers into the cycle), the shared_ptr reference counts cannot reach zero and the memory is leaked. To prevent this, one of the pointers in the cycle can be made weak.

总之,weak_ptr很弱,只记录状态信息,不保证一定存在,同时(主要)为了解决shared_ptr造成的循环引用,通常也不会单独出现,必须要转换成shared_ptr.
对比rust中的weak也是几乎一样的设计理由和使用条件,不保证引用一定存在,所以它返回Option< Rc < T > >,代码写法即upgrade升级到Rc,或将Rc降级到weak。

代码示例:

use std::rc::{Rc, Weak};
use std::cell::RefCell;
#[derive(Debug)]
struct Node {value: i32,parent: RefCell<Weak<Node>>,children: RefCell<Vec<Rc<Node>>>,
}fn main() {let _leaf = Rc::new(Node {value: 3,parent: RefCell::new(Weak::new()),children: RefCell::new(vec![]),});
}

Deref和Drop

  1. Deref: 将引用中的实际值解出并使用,是Rust中最常见的隐式转换,如将String类型传入 &str入参时等等
  2. Drop: 释放资源,类似于析构函数,同样的,有默认实现,也有主动重写。
  3. Deref 是特征,一般开发者仅会为自定义的智能指针实现解引用特征。
  4. 解引用可递推,所以在隐式转换时常常有多层的解引用。

总结

本章结合题目非常适合链表练习。

如有勘误,敬请指出。

相关文章:

【Rust中的智能指针】

Rust中的智能指针 什么是智能指针&#xff1f;什么是Rust中的智能指针&#xff1f;Rust中的智能指针BoxBox的使用场景 Rust中的智能指针Rc与Arcrust中的RefCellrefcell的缺点&#xff1a;rust中的weak先来看看C中的weak_ptr定义代码示例&#xff1a; Deref和Drop 总结 什么是智…...

基于深度学习的社交网络中的社区检测

在社交网络分析中&#xff0c;社区检测是一项核心任务&#xff0c;旨在将网络中的节点&#xff08;用户&#xff09;划分为具有高内部连接密度且相对独立的子群。基于深度学习的社区检测方法&#xff0c;通过捕获复杂的网络结构信息和节点特征&#xff0c;在传统方法基础上实现…...

【Python基础】

一、编程语言介绍 1、分类 机器语言 (直接用 0 1代码编写&#xff09;汇编语言 &#xff08;英文单词替代二进制指令&#xff09;高级语言 2、总结 1、执行效率&#xff1a;机器语言&#xff1e;汇编语言>高级语言&#xff08;编译型>解释型&#xff09; 2、开发效率&…...

【玉米叶部病害识别】Python+深度学习+人工智能+图像识别+CNN卷积神经网络算法+TensorFlow

一、介绍 玉米病害识别系统&#xff0c;本系统使用Python作为主要开发语言&#xff0c;通过收集了8种常见的玉米叶部病害图片数据集&#xff08;‘矮花叶病’, ‘健康’, ‘灰斑病一般’, ‘灰斑病严重’, ‘锈病一般’, ‘锈病严重’, ‘叶斑病一般’, ‘叶斑病严重’&#x…...

【设计模式】如何用C++实现依赖倒置

【设计模式】如何用C实现依赖倒置 一、什么是依赖倒置&#xff1f; 依赖倒置原则&#xff08;Dependency Inversion Principle&#xff0c;DIP&#xff09;是SOLID面向对象设计原则中的一项。它的核心思想是&#xff1a; 高层模块不应该依赖于低层模块&#xff0c;两者都应该…...

使用onnxruntime-web 运行yolov8-nano推理

ONNX&#xff08;Open Neural Network Exchange&#xff09;模型具有以下两个特点促成了我们可以使用onnxruntime-web 直接在web端上运行推理模型&#xff0c;为了让这个推理更直观&#xff0c;我选择了试验下yolov8 识别预览图片&#xff1a; 1. 跨平台兼容性 ONNX 是一种开…...

Gin框架html/vue前端使用hls.js播放/点播m3u8(hls)格式视频

说明 在web应用开发时遇到在线播放m3u8格式视频&#xff0c;由于m3u8是多分片视频&#xff0c;原生video标签无法直接播放&#xff0c;所以需要js对m3u8处理才能播放&#xff0c;网上有很多插件&#xff0c;这里我选择最近简单方法hls.js播放&#xff0c;引入一个js文件即可。…...

HarmonyOS 私仓搭建

1. HarmonyOS 私仓搭建 私仓搭建文档&#xff1a;https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-ohpm-repo-quickstart-V5   发布共享包[https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-har-publish-0000001597973129-V5]…...

Mybatis学习笔记(二)

八、多表联合查询 (一) 多表联合查询概述 在开发过程中单表查询不能满足项目需求分析功能&#xff0c;对于复杂业务来讲&#xff0c;关联的表有几张&#xff0c;甚至几十张并且表与表之间的关系相当复杂。为了能够实业复杂功能业务&#xff0c;就必须进行多表查询&#xff0c…...

Google“Big Sleep“人工智能项目发现真实软件漏洞

据Google研究人员称&#xff0c;该公司的一个人工智能项目足够聪明&#xff0c;能够自行发现现实世界中的软件漏洞&#xff1b;Google的人工智能项目最近在开源数据库引擎 SQLite 中发现了一个之前未知的可利用漏洞。 该公司随后在正式软件发布之前报告了这一漏洞&#xff0c;这…...

npm入门教程5:package.json

一、package.json 文件的作用 依赖管理&#xff1a;列出项目所依赖的包&#xff08;库&#xff09;及其版本&#xff0c;便于其他开发者或自动化工具快速安装和更新这些依赖。元数据描述&#xff1a;提供项目的描述、作者、许可证等元信息&#xff0c;有助于项目的管理和维护。…...

docker-高级(待补图)

文章目录 数据卷(Volume)介绍查看方法删除方法绑定方法匿名绑定具名绑定Bind Mount 数据卷管理 网络bridge(桥接模式 默认)HOST(主机模式)Nonecontainer(指定一个容器进行关联网络共享)自定义(推荐)docker network 命令创建网络docker network create 实例展示-自定义实例展示-…...

Qt 文件目录操作

Qt 文件目录操作 QDir 类提供访问系统目录结构 QDir 类提供对目录结构及其内容的访问。QDir 用于操作路径名、访问有关路径和文件的信息以及操作底层文件系统。它还可以用于访问 Qt 的资源系统。 Qt 使用“/”作为通用目录分隔符&#xff0c;与“/”在 URL 中用作路径分隔符…...

Pandas 数据清洗

1.数据清洗定义 数据清洗是对一些没有用的数据进行处理的过程。很多数据集存在数据缺失、数据格式错误、错误数据或重复数据的情况&#xff0c;如果要使数据分析更加准确&#xff0c;就需要对这些没有用的数据进行处理。 2.清洗空值 DataFrame.dropna(axis0, howany, threshN…...

IO学习笔记

当前需求&#xff0c;希望进行游戏可以保存游戏进度&#xff0c;可以将游戏的进度保存到一个文本文件&#xff0c;每一次打完游戏更新文本内容&#xff0c;下一次打游戏读取游戏进度&#xff0c;这里就涉及到两个知识IO流和File的知识。 File类 概述 java.io.File 类是文件…...

汇编练习-1

1、要求 练习要求引自《汇编语言-第4版》实验10.3(P209页) -编程&#xff0c;将data段中的数据&#xff0c;以10进制的形式显示出来 data segment dw 123,12666,1,8,3,38 data ends 2、实现代码(可惜没找到csdn对8086汇编显示方式) assume cs:codedata segmentdw 16 dup(0) ;除…...

初识二叉树( 二)

初识二叉树 二 实现链式结构二叉树前中后序遍历遍历规则代码实现 结点个数以及高度等层序遍历判断是否为完全二叉树 实现链式结构二叉树 ⽤链表来表示⼀棵二叉树&#xff0c;即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成&#xff0c;数据域和左右指针…...

AcWing1077-cnblog

问题背景 给定一个树形结构的图&#xff0c;每个节点代表一个地点&#xff0c;每个节点有一个守卫的代价。我们希望以最低的代价在树的节点上放置守卫&#xff0c;使得整棵树的所有节点都被监控。可以通过三种方式覆盖一个节点&#xff1a; 由父节点监控。由子节点监控。自己…...

五、SpringBoot3实战(1)

一、SpringBoot3介绍 1.1 SpringBoot3简介 SpringBoot版本&#xff1a;3.0.5 https://docs.spring.io/spring-boot/docs/current/reference/html/getting-started.html#getting-started.introducing-spring-boot 到目前为止&#xff0c;你已经学习了多种配置Spring程序的方式…...

练习LabVIEW第三十三题

学习目标&#xff1a; 刚学了LabVIEW&#xff0c;在网上找了些题&#xff0c;练习一下LabVIEW&#xff0c;有不对不好不足的地方欢迎指正&#xff01; 第三十三题&#xff1a; 用labview编写一个判断素数的程序 开始编写&#xff1a; LabVIEW判断素数&#xff0c;首先要搞…...

探索800+免费接口:API资源库的高效集成指南

探索800免费接口&#xff1a;API资源库的高效集成指南 【免费下载链接】public-api-lists A collective list of free APIs for use in software and web development &#x1f680; (Clone of https://github.com/public-apis/public-apis) 项目地址: https://gitcode.com/G…...

智能家居新视野:LingBot-Depth让机器人看懂复杂室内场景

智能家居新视野&#xff1a;LingBot-Depth让机器人看懂复杂室内场景 1. 引言&#xff1a;当机器人走进真实家庭环境 想象一下&#xff0c;你刚买的家用机器人第一次进入客厅时的场景&#xff1a;阳光透过窗帘在地板上投下斑驳的光影&#xff0c;茶几上的玻璃杯反射着吊灯的光…...

KMS_VL_ALL_AIO:智能激活脚本的高效办公解决方案

KMS_VL_ALL_AIO&#xff1a;智能激活脚本的高效办公解决方案 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 在数字化办公环境中&#xff0c;Windows系统和Office办公套件的激活管理常常成为用户…...

300FPS的实时目标跟踪是怎么炼成的?手把手拆解KCF算法里的数学魔法

300FPS实时目标跟踪背后的数学魔法&#xff1a;KCF算法深度解密 在计算机视觉领域&#xff0c;实时目标跟踪一直是个令人着迷又充满挑战的问题。想象一下&#xff0c;当你在观看一场足球比赛时&#xff0c;摄像机需要实时锁定某个球员&#xff1b;或者当自动驾驶汽车行驶时&am…...

SDMatte与版本控制:使用Git管理模型权重、训练脚本与实验数据

SDMatte与版本控制&#xff1a;使用Git管理模型权重、训练脚本与实验数据 1. 为什么机器学习项目需要版本控制 在SDMatte这类图像处理模型的开发过程中&#xff0c;我们经常遇到这样的困扰&#xff1a;上周训练的那个效果最好的模型权重文件找不到了&#xff1b;修改了训练脚…...

Ryzen平台硬件调试终极指南:从问题诊断到系统优化的实战路径

Ryzen平台硬件调试终极指南&#xff1a;从问题诊断到系统优化的实战路径 【免费下载链接】SMUDebugTool A dedicated tool to help write/read various parameters of Ryzen-based systems, such as manual overclock, SMU, PCI, CPUID, MSR and Power Table. 项目地址: http…...

Wan2.1-UMT5一键部署教程:基于Python的AI视频生成WebUI快速搭建

Wan2.1-UMT5一键部署教程&#xff1a;基于Python的AI视频生成WebUI快速搭建 你是不是也对那些能根据文字描述生成视频的AI工具感到好奇&#xff1f;想自己动手搭建一个来玩玩&#xff0c;但又担心过程太复杂&#xff0c;被各种环境配置和依赖问题劝退&#xff1f; 别担心&…...

WaveTools终极指南:免费解锁《鸣潮》流畅体验的完整解决方案

WaveTools终极指南&#xff1a;免费解锁《鸣潮》流畅体验的完整解决方案 【免费下载链接】WaveTools &#x1f9f0;鸣潮工具箱 项目地址: https://gitcode.com/gh_mirrors/wa/WaveTools 还在为《鸣潮》游戏卡顿、帧率不稳而烦恼吗&#xff1f;WaveTools鸣潮工具箱为你带…...

SiameseUIE在CSDN社区的应用:技术文章智能分析

SiameseUIE在CSDN社区的应用&#xff1a;技术文章智能分析 1. 引言 CSDN社区每天都有成千上万的技术文章发布&#xff0c;涵盖了从编程语言到人工智能的各个领域。面对如此庞大的内容量&#xff0c;如何快速准确地理解每篇文章的核心内容、自动生成标签、进行智能分类&#x…...

Markdown到PowerPoint转换技术:md2pptx的架构创新与工程实践

Markdown到PowerPoint转换技术&#xff1a;md2pptx的架构创新与工程实践 【免费下载链接】md2pptx Markdown To PowerPoint converter 项目地址: https://gitcode.com/gh_mirrors/md/md2pptx 在技术文档创作和演示文稿制作领域&#xff0c;传统工作流存在显著效率瓶颈。…...