深圳做网站j华信科/网站的seo 如何优化
目录
- 一、概念
- 二、Box\<T\>
- 2.1 概念与应用场景
- 2.2 简单应用
- 2.3 递归类型的创建
- 三、通过Deref trait将智能指针当作常规引用处理
- 3.1 常规引用
- 3.2 像引用一样使用Box\<T\>
- 3.3 自定义智能指针
- 3.4 函数和方法的隐式解引用强制转换
- 3.5 解引用强制转换与可变性交互
- 四、使用Drop Trait清理代码
- 4.1 自动运行
- 4.2 手动丢弃
一、概念
- 在Rust中,引用是只是借用数据的指针,智能指针拥有它们所指向的数据的所有权;
- 智能指针通常使用结构体实现;
- 智能指针实现了
Deref trait
,值可以被当作引用对待; - 智能指针实现了
Drop trait
,当值离开作用域时,其所指向的堆数据也去被清除; - 常用的智能指针见下表
指针 | 功能说明 |
---|---|
Box<T> | 用于在堆上分配值,允许在编译时执行不可变或可变借用检查 |
Rc<T> | 一个引用计数类型,相同数据可以有多个所有者,仅允许在编译时执行不可变借用检查 |
RefCell<T> | 允许在运行时执行不可变或可变借用检查;可以在即使RefCell<T> 自身是不可变的情况下修改其内部的值 |
Ref<T> 和 RefMut<T> | 通过RefCell<T> 访问 |
- 内部可变性模式:在不可变值内部改变值;
二、Box<T>
2.1 概念与应用场景
- box是最简单最直接的智能指针,其类型是
box<T>
; - box主要应用于以下场景:
- 编译时未知大小的类型,但使用时却需要知道它的确切大小;
- 有大量数据且希望在确保数据不被拷贝的情况下转移所有权;
- 只关心值的类型是否实现了特定 trait;
2.2 简单应用
fn main(){let b = Box::new(5);println!("b = {}", b);
}
- 变量b指向了分配在堆上的值为5的Box;
- b拥有这块内存的所有权,离开作用域后堆内存被自动释放;
2.3 递归类型的创建
- Rust需要在编译时知道类型占用的空间大小;
- box的已知大小,让其可以在循环类型定义中插入box,就可以创建递归类型;
enum List{Cons(i32, Box<List>),Nil,
}use crate::List::{Cons, Nil};
fn main() {let list = Cons(1,Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}
- Cons成员将需要一个
i32
类型的空间大小以及box指针数据的空间; - Nil成员不存储值,因此它比Cons成员需要更少的空间;
- 看起来像这样
- 如果不用Box定义递归,写成下面这样
enum List{Cons(i32, List),Nil,
}use crate::List::{Cons, Nil};
fn main() {let list = Cons(1, Cons(2, Cons(3, Nil)));
}
- 则编译报错,表明类型占用的空间无限大;
- 其空间排布类型于
三、通过Deref trait将智能指针当作常规引用处理
- 实现Deref trait可以让使用者重载解引用运算符(dereference operator)
*
; - 这种方式实现Deref trait的智能指针可以被当作常规引用来对待,可以编写操作引用的代码并用于智能指针;
3.1 常规引用
- 常规引用是一种指针类型;
fn main() {let x = 5;let y = &x;assert_eq!(5, x);assert_eq!(5, *y);
}
- y等于x的引用,使用
*y
访问x的值;
3.2 像引用一样使用Box<T>
let x = 5;let y = Box::new(x);assert_eq!(5, x);assert_eq!(5, *y);
- 代码可正常运行不报错;
3.3 自定义智能指针
use std::ops::Deref;struct MyBox<T>(T);impl<T> MyBox<T> {fn new(x: T) -> MyBox<T> {MyBox(x)}
}impl<T> Deref for MyBox<T>{type Target = T;fn deref(&self) -> &T {&self.0}
}fn main() {let x = 5;let y = MyBox::new(x);assert_eq!(5, x);assert_eq!(5, *y);
}
- MyBox<T> 被定义为包含一个元素的元组结构体;
- new函数获取一个T类型的参数并返回一个存入传入值的实例;
- 为MyBox实现
Deref
trait才能启动*
运算符的解引用功能; impl<T> Deref for MyBox<T>
中的type Target = T 定义了此trait的关联类型;deref
方法返回了一个值的引用,如果直接返回值,则值的选择权将被移出self;- 当使用
*y
时,底层运行了代码*(y.deref())
;
3.4 函数和方法的隐式解引用强制转换
- 解引用强制转换只能工作在实现了
Deref
trait 的类型上; - 解引用强制转换是将一种类型隐式转换为另外一种类型的引用;
- 前一种类型实现了
Deref
trait,并且其关联类型是后一种类型;
例如,解引用强制转换可以将 &String 转换为 &str,因为类型 String 实现了 Deref trait 并且其关联类型是 str;
#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Deref for String {type Target = str;#[inline]fn deref(&self) -> &str {unsafe { str::from_utf8_unchecked(&self.vec) }}
}
- 将特定类型的值的引用传递给函数且与函数定义的参数类型不匹配时,会发生解引用强制转换;
- 此时有一系列的
deref
方法被调用,将我们提供的参数类型转换成函数或方法需要的参数类型; - 解引用强制转换功能可以让开发者编写函数和方法调用时无需增加过多显式使用
&和*
引用和解引用。 - 解引用强制转换功能也使得开发者可以编写更多同时作用于引用或智能指针的代码;
use std::ops::Deref;struct MyBox<T>(T);impl<T> MyBox<T> {fn new(x: T) -> MyBox<T> {MyBox(x)}
}impl<T> Deref for MyBox<T>{type Target = T;fn deref(&self) -> &T {&self.0}
}fn hello(name: &str){println!("Hello, {}", name);
}fn main() {let m = MyBox::new(String::from("Rust"));hello(&m);
}
- main函数中的m为MyBox<String>值的引用;
- MyBox<T>上实现了
Deref
trait,Rust可以通过deref调用将&MyBox<String>
变为&String
; - 再次调用deref将&String 变为 &str;
- 如果没有实现解引用强制转换,为了使用
&MyBox<String>
类型的值调用hello函数,应该这样写
fn main() {let m = MyBox::new(String::from("Rust"));hello(&(*m)[..]);
}
- (*m) 将 MyBox<String> 解引用为 String;
- &和[…] 获取了整个 String 的字符串 slice 来匹配 hello 函数的参数;
- 没有解引用强制转换所有这些符号混在一起将更难以读写和理解;
- Rust的解引用强制转换发生在编译,因此在运行时没有损耗!
3.5 解引用强制转换与可变性交互
- 类似于使用 Deref trait 重载不可变引用的
*
运算符,Rust提供了DerefMuttrait
用于重载可变引用的*
运算符; - Rust 在发现类型和 trait 的实现满足以下三种情况时会进行解引用强制转换;
- 当 T: Deref<Target=U> :从 &T 到 &U
如果有一个&T,而T实现了返回U类型的Deref,则可以直接得到&U - 当 T: DerefMut<Target=U> :从 &mut T 到 &mut U
对于可变引用有着与第一种相同的行为; - 当 T: Deref<Target=U> :从 &mut T 到 &U
Rust也会将可变引用强转为不可变引用,但是反之是不可能的,因为不可变引用永远也不能强转为可变引用;
- 当 T: Deref<Target=U> :从 &T 到 &U
四、使用Drop Trait清理代码
4.1 自动运行
- 通过实现
Drop
trait指定变量离开作用域时被执行的代码; - 可以理解为析构函数;
struct CustomSmartPointer {data: String,
}impl Drop for CustomSmartPointer {fn drop(&mut self) {println!("Dropping CustomSmartPointer with data `{}`!", self.data);}
}fn main() {{let c = CustomSmartPointer { data: String::from("stuff c") };}let d = CustomSmartPointer { data: String::from("stuff d") };let e = CustomSmartPointer { data: String::from("stuff e") };println!("CustomSmartPointers created.");
}
- main函数中离开最内层的大括号后,变量c首先离开作用域,自动调用
drop
方法; - 然后打印CustomSmartPointers created.
- 变量d、e最后离开作用域,再自动调用对应的
drop
方法; - d、e的输出结果显示,以先进后出的方式调用drop方法;
4.2 手动丢弃
- 不能显式的调用
drop
方法; - 如果要在作用域结构之前强制释放变量,使用
drop(x)
实现;
fn main() {{let c = CustomSmartPointer { data: String::from("stuff c") };}let d = CustomSmartPointer { data: String::from("stuff d") };drop(d);let e = CustomSmartPointer { data: String::from("stuff e") };println!("CustomSmartPointers created.");
}
运行代码,可以发现d
被提前析构;
相关文章:

21.智能指针(上)
目录 一、概念二、Box\<T\>2.1 概念与应用场景2.2 简单应用2.3 递归类型的创建 三、通过Deref trait将智能指针当作常规引用处理3.1 常规引用3.2 像引用一样使用Box\<T\>3.3 自定义智能指针3.4 函数和方法的隐式解引用强制转换3.5 解引用强制转换与可变性交互 四、…...

Jenkins+gitee流水线部署springboot项目
目录 前言 一、软件版本/仓库 二、准备工作 2.1 安装jdk 11 2.2 安装maven3.9.7 2.3 安装docker 2.4 docker部署jenkins容器 三、jenkins入门使用 3.1 新手入门 3.2 jenkins设置环境变量JDK、MAVEN、全局变量 3.2.1 jenkins页面 3.2.2 jenkins容器内部终端 3.2.3 全…...

python--os.walk()函数使用(超详细)
在Python 3.7中,os.walk()函数的用法与早期版本(包括Python 3.4及之后)保持一致。os.walk()是一个用于遍历目录树的生成器函数,它生成给定目录中的文件名。这个函数没有直接的参数(除了你要遍历的目录路径,…...

基础名词概念
了解以下基础名词概念/定义: IP地址、子网掩码、网关、DNS、DHCP、MAC地址、网络拓扑、路由器、交换机、VPN、端口、TCP、UDP、HTTP、HTTPS、OSI模型、ARP、NAT、VLAN、FTP、SMTP、IMAP、SSL、ICMP、链路聚合、TRUNK、直连路由、静态路由、动态路由、IPV6 端口&am…...

ArkTS开发系列之Web组件的学习(2.9)
上篇回顾:ArkTS开发系列之事件(2.8.2手势事件) 本篇内容: ArkTS开发系列之Web组件的学习(2.9) 一、知识储备 Web组件就是用来展示网页的一个组件。具有页面加载、页面交互以及页面调试功能 1. 加载网络…...

postman接口工具的详细使用教程
Postman 是一种功能强大的 API 测试工具,可以帮助开发人员和测试人员轻松地发送 HTTP 请求并分析响应。以下是对 Postman 接口测试工具的详细介绍: 安装与设置 安装步骤 访问 Postman 官网,点击右上角的“Download”按钮。 选择你的操作系统…...

C语言经典例题-17
1.最小公倍数 正整数A和正整数B的最小公倍数是指能被A和B整除的最小的正整数,设计一个算法,求输入A和B的最小公倍数。 输入描述:输入两个正整数A和B。 输出描述:输出A和B的最小公倍数。 输入:5 7 输出:…...

鸿蒙学习(-)
.ets文件结构 //页面入口 Entry //组件 Component struct test{//页面结构build(){//容器 **一个页面只能有一个根容器,父容器要有大小设置**}1、Column 组件 沿垂直方向布局的组件,可以包含子组件 接口 Column({space}) space的参数为string | numbe…...

【TB作品】MSP430G2553,单片机,口袋板, 烘箱温度控制器
题3 烘箱温度控制器 设计一个基于MSP430的温度控制器,满足如下技术指标: (1)1KW 电炉加热,最度温度为110℃ (2)恒温箱温度可设定,温度控制误差≦2℃ (3)实时显…...

PCM、WAV,立体声,单声道,正弦波等音频素材
1)PCM、WAV音频素材,分享给将要学习或者正在学习audio开发的同学。 2)内容属于原创,若转载,请说明出处。 3)提供相关问题有偿答疑和支持。 常用的Audio PCM WAV不同采样率,不同采样深度&#…...

基于深度学习的图像去雾
基于深度学习的图像去雾 图像去雾是指从有雾的图像中恢复清晰图像的过程。传统的图像去雾方法(如暗原色先验、图像分层法等)在某些情况下表现良好,但在复杂场景下效果有限。深度学习方法利用大量的数据和强大的模型能力,在图像去…...

中国电子学会青少年编程等级考试真题下载
全国青少年软件编程等级考试真题下载,有答案解析 1. 图形化Scratch一级下载 链接:https://pan.baidu.com/s/1C9DR9-hT1RUY3417Yc8RZQ?pwdg8ac 提取码:g8ac 2.图形化Scratch二级下载 链接:https://pan.baidu.com/s/1HI7GaI4ii…...

PostMan动态设置全局变量
1. 前言 在开发过程中调试接口,一般都会使用PostMan。 其中有几个变量可能是好几个接口共用的,就会出现频繁手动复制(ctrlc)、粘贴(ctrlv)的情况。 这个过程得非常留意,生怕复制错了,或删减了某些东西,导致接口报错。…...

ACL 2023事件相关(事件抽取、事件关系抽取、事件预测等)论文汇总
ACL 2023事件抽取相关(事件抽取、事件关系抽取、事件预测等)论文汇总,后续会更新全部的论文讲解。 Event Extraction Code4Struct: Code Generation for Few-Shot Event Structure Prediction 数据集:ACE 2005 动机:与自然语言相比…...

力扣:59. 螺旋矩阵 II(Java,模拟)
目录 题目描述示例 1:代码实现 题目描述 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1: 输入:n 3 输出:[[1,2,3],[8,9,4],[7,6,5…...

记录SpringBoot启动报错解决
记录SpringBoot启动报错解决 报错现场 Failed to configure a DataSource: url attribute is not specified and no embedded datasource could be configured. Reason: Failed to determine a suitable driver class Action: Consider the following:If you want an embedde…...

微软代码页标识符 (Code Page Identifiers)
代码页标识符 (Code Page Identifiers) 双语对照 Identifiere标识符.NET Name.NET 名称Additional information其他信息037IBM037IBM EBCDIC US-CanadaIBM EBCDIC US-Canada437IBM437OEM United StatesOEM 美国500IBM500IBM EBCDIC InternationalIBM EBCDIC 国际字符集708ASMO…...

刷题——二叉树的后续遍历
方法一:双指针法 void postorder(TreeNode* root, vector<int>&res){if(root NULL) return;postorder(root->left,res);postorder(root->right,res);res.push_back(root->val);}vector<int> postorderTraversal(TreeNode* root) {// wri…...

用友U8 Cloud smartweb2.showRPCLoadingTip.d XXE漏洞复现
0x01 产品简介 用友U8 Cloud 提供企业级云ERP整体解决方案,全面支持多组织业务协同,实现企业互联网资源连接。 U8 Cloud 亦是亚太地区成长型企业最广泛采用的云解决方案。 0x02 漏洞概述 用友U8 Cloud smartweb2.showRPCLoadingTip.d 接口处存在XML实体,攻击者可通过该漏…...

React中的事件绑定的四种方式
1.在构造函数中绑定事件 constructor(props) {super(props);this.handleClick this.handleClick.bind(this);}2.在调用时显式绑定 <button onClick{this.handleClick.bind(this)}>Click me</button>3.使用箭头函数 handleClick () > {console.log(Button cli…...

小文件过多的解决方法(不同阶段下的治理手段,SQL端、存储端以及计算端)
上一篇介绍了小文件出现的原因以及为什么治理小文件问题迫在眉睫,本篇将为读者讲述在不同阶段下小文件治理的最佳手段以及如何针对性的解决小文件过多的问题。 小文件过多如何解决、治理方法 小文件是特别常见的现象,解决小文件问题迫在眉睫࿰…...

SGPT论文阅读笔记
这是篇想要用GPT来提取sentence embedding的工作,提出了两个框架,一个是SGPT-BE,一个是SGPT-CE,分别代表了Bi-Encoder setting和Cross-Encoder setting。CE的意思是在做阅读理解任务时,document和query是一起送进去&am…...

虚拟机与主机的网络桥接
虚拟机网路桥接是一种网络配置方式,它允许虚拟机与物理网络中的其他设备直接通信。在桥接模式下,虚拟机的网络接口通过主机的物理网卡连接到局域网中,就像主机本身一样,拥有自己的MAC地址和IP地址。这种方式使得虚拟机可以像独立的…...

urfread刷算法题day1|LeetCode2748.美丽下标的数目
题目 题目链接 LeetCode2748.美丽下标对的数目 题目描述 给你一个下标从 0 开始的整数数组 nums 。 如果下标对 i、j 满足 0 ≤ i < j < nums.length , 如果 nums[i] 的 第一个数字 和 nums[j] 的 最后一个数字 互质 , 则认为 nums[i] 和 nums…...

面向对象修炼手册(四)(多态与空间分配)(Java宝典)
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀面向对象修炼手册 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 前言 1 多态 1.1 多态的形式&…...

基于UDP的网络聊天室(多线程实现收和发消息)
要求:1.有新用户登录,其他在线的用户可以收到登录信息 2.有用户群聊,其他在线的用户可以收到群聊信息 3.有用户退出,其他在线的用户可以收到退出信息 4.服务器可以发送系统信息 效果图: service.c #include <head…...

【脚本工具库】随机抽取数据 - 图像和标签对应(附源码)
在数据处理和机器学习任务中,我们经常需要从大规模数据集中随机抽取一定数量的图像及其对应的标签文件,以便进行模型训练、验证或测试。手动操作不仅耗时,而且容易出错。为了解决这个问题,我们可以编写一个Python脚本,…...

【python】eval函数
1.eval函数的语法及用法 (1)语法:eval(expression) 参数说明: expression:必须为字符串表达式,可为算法,也可为input函数等。 说明:表达式必需是字符串,否则会报错&a…...

实战|记一次java协同办公OA系统源码审计
前言 因为笔者也是代码审计初学者,写得不好的地方请见谅。该文章是以项目实战角度出发,希望能给大家带来启发。 审计过程 审计思路 1、拿到一个项目首先要看它使用了什么技术框架,是使用了ssh框架,还是使用了ssm框架ÿ…...

浅浅谈谈如何利用Javase+多线程+计算机网络的知识做一个爬CSDN阅读量总访问量的程序
目录 我们发现csdn的文章 首先为了印证我们的想法 我们用postman往csdn我们任意一篇文章发起post请求 发送请求 编辑获得响应结果 我们发现我们的阅读量上涨 PostRequestSender类 但是我们经过测试发现 定义一个字符串数组 把URL放进去 然后延迟启动 在线程池里面…...