当前位置: 首页 > 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;首先要搞…...

手游刚开服就被攻击怎么办?如何防御DDoS?

开服初期是手游最脆弱的阶段&#xff0c;极易成为DDoS攻击的目标。一旦遭遇攻击&#xff0c;可能导致服务器瘫痪、玩家流失&#xff0c;甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案&#xff0c;帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

GC1808高性能24位立体声音频ADC芯片解析

1. 芯片概述 GC1808是一款24位立体声音频模数转换器&#xff08;ADC&#xff09;&#xff0c;支持8kHz~96kHz采样率&#xff0c;集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器&#xff0c;适用于高保真音频采集场景。 2. 核心特性 高精度&#xff1a;24位分辨率&#xff0c…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

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 为工程 名&…...

系统掌握PyTorch:图解张量、Autograd、DataLoader、nn.Module与实战模型

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文通过代码驱动的方式&#xff0c;系统讲解PyTorch核心概念和实战技巧&#xff0c;涵盖张量操作、自动微分、数据加载、模型构建和训练全流程&#…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...