Rust语言入门教程(八) - 引用与借用

上一章的内容中我们讨论了Rust的所有权系统,当我们不想移动值的所有权时,我们可以使用引用和借用,而这正是本章想要讨论的问题。

引用(References)

引用允许你访问或修改数据而无需获取数据的所有权。在 Rust 中,有两种类型的引用:

  • 不可变引用(&T):
    1. 它允许你读取数据,但不能修改它。
    2. 你可以同时拥有多个不可变引用。
    3. 当存在不可变引用时,不能再有可变引用。
  • 可变引用(&mut T):
    1. 它允许你读取和修改数据。
    2. 同一时间,只能有一个可变引用指向同一数据。
    3. 当存在可变引用时,不能再有其他可变或不可变引用,为了防止写竞争或读取数据时数据改变。

请添加图片描述
如上图所示, 在多个线程中如果都存在对同一个值的引用时, 在没有锁的情况下, 对同一个变量进行多个可变引用显然是不安全的。

借用(Borrowing)

借用是指使用引用来访问数据的行为。当你创建一个引用时,实际上是在“借用”值。借用规则如下:

  • 数据的所有者不变:当你借用一个值时,该值的所有权不会转移。
  • 作用域和生命周期:引用必须在其所指向的数据的作用域内有效。这就是 Rust 中的生命周期(lifetime)概念。

引用使用示例

let s1 = String::from("abc");
do_stuff(&s1);
println!("{}", s1);

fn do_stuff(s: &String) {
	// do stuff
}

上面的代码中, 我们还是创建了一个do_stuff()函数, 与上一章不同的是, 我们这个函数接受的参数是一个字符串的引用, &String前面的&符号,表示这是一个String类型的引用, 因此,当调用该函数时,我们传递给他的是对s1的引用, 而s1依然保留了对它的值的所有权。do_stuff()借用了一个对值的引用,它将引用而不是值移动到了函数中, 在函数的作用域结束时, 引用被销毁,我们的借用行为也在此时结束。在函数执行完以后,我们还可以正常的使用s1, 因为其值的所有权没有被移动过。

从内存的视角出发, 当创建一个指向s1的引用时, Rust会创建一个指向s1的指针。 但在Rust中,我们几乎从来不会谈论指针的行为,因为Rust语言在很大程度上会自动处理他们的创建和销毁,Rust中的有一个生命周期的概念,就是用来确保指针始终有效。
请添加图片描述
Rust的编译器可以保证, 不会让用户创建一个引用的存活时间超过它引用的源数据的存活时间,并且指针永远不能指向Null。

可变与不可变引用

引用与变量一样, 默认是不可变的,这意味着,即使被引用的值是可变的,也不能直接通过引用来修改它,例如下面这段代码:

let mut s1 = String::from("abc");
do_stuff(&s1);

fn do_stuff(s: &String) {
	s.insert_str(0, "Hi, "); // Error
}

虽然s1被声明为可变的, 但是它的引用默认是不可变的,因此在函数中试图修改s1的值,编译器就会报错。想要通过引用修改被引用的值,可以将引用声明为可变引用:

let mut s1 = String::from("abc");
do_stuff(&mut s1);

fn do_stuff(s: &mut String) {
	s.insert_str(0, "Hi, ");
}

注意可变引用的格式有些许特别: &mut 变量/类型

解引用

注意到了吗,在上面的例子中的函数中,修改s的值的时候,并没有对其先解引用。我们直接使用了.操作符来访问可变引用上的字符串函数,就像我们在对被引用的值本身进行操作一样。

在Rust中,函数或字段的.运算符会自动对引用进行解引用,获取到最终被引用的值。这样的话,在我们使用.运算符的时候,就不用费劲搞清楚某个变量到底是一个值,还是一个引用,甚至是一个引用的引用了。

那怎么样可以手动的进行解引用的操作呢,和大多数语言一样,在前面加上一个*即可, 解引用操作符的优先级很低,因此需要加上( )

let mut s1 = String::from("abc");
do_stuff(&mut s1);

fn do_stuff(s: &mut String) {
	(*s).insert_str(0, "Hi, ");
}

注意上面说的是在.运算符的情况下, Rust会进行自动的解引用, 对于大多数的其他运算符,例如赋值运算,是需要手动进行解引用的:

let mut s1 = String::from("abc");
do_stuff(&mut s1);

fn do_stuff(s: &mut String) {
	s.insert_str(0, "Hi, ");
	*s = String::from("Replacement");
}

小结

本章介绍了引用和借用的含义,以及使用方法,让我们来简单回顾一下:

x 			// 变量
&x 			//变量的不可变引用
&mut x 		// 变量的可变引用

i32			// 类型
&i32 		// 该类型的不可变引用的类型
&mut i32 	// 该类型的可变引用的类型

x: &mut i32 // x是某个值的可变引用
*x			// *x解引用获取到被引用的值, 可变

x: &i32		// x是某个值的不可变引用
*x			// 解引用获取到被引用的值,不可变

下一章将开始介绍Rust中的结构体。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CSS清除浮动的八种方法

我们为什么需要清除浮动&#xff0c;如果我们不清除浮动会发生什么呢&#xff1f; 基础样式&#xff0c;没清除浮动之前代码&#xff1a; 可复制也可以自己手动布局&#xff0c;后可尝试使用下面介绍的方法练习清除浮动 <!DOCTYPE html> <html lang"en">…

[Java] 阿里一面~说一下ArrayList 与 LinkedList 区别

文章目录 是否保证线程安全底层数据结构插入和删除是否受元素位置的影响是否支持快速随机访问内存空间占用&#xff1a; 是否保证线程安全 ArrayList 和 LinkedList 都是不同步的&#xff0c;也就是不保证线程安全&#xff1b; 底层数据结构 ● ArrayList 底层使用的是 Obje…

常见树种(贵州省):022绣线菊、月月青、金合欢、胡枝子、白刺花

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、绣线菊…

C语言:写一个函数,实现3*3矩阵的转置(指针)

分析&#xff1a; 在主函数 main 中&#xff0c;定义一个 3x3 的整型数组 a&#xff0c;并定义一个指向整型数组的指针 p。然后通过循环结构和 scanf 函数&#xff0c;从标准输入中读取用户输入的 3x3 矩阵的值&#xff0c;并存储到数组 a 中。 接下来&#xff0c;调用 mov…

汇编:关于栈的知识

1.入栈和出栈指令 2. SS与SP 3. 入栈与出栈 3.1 执行push ax ↑↑ 3.2 执行pop ax ↓↓ 3.3 栈顶超界的问题 4. 寄存器赋值 基于8086CPU编程时&#xff0c;可以将一段内存当作栈来使用。一个栈段最大可以设为64KB&#xff08;0-FFFFH&#xff09;。 1.入栈和出栈指令…

003、ArkTS开发实践

之——尝试 杂谈 学习声明式UI语法&#xff1a; 正文 1.声明式UI 1.1 声明式描述 想要什么样子就直接描述&#xff1a; 1.2 状态驱动视图更新 2.自定义组件 对页面内容进行合理抽象&#xff0c;组合基础组件&#xff0c;封装成自定义组件。 自定义子组件&#xff0c;为后续使…

基于51单片机的全自动洗衣机proteus仿真设计

标题目录 &#x1f4ab;51单片机全自动洗衣机proteus仿真设计&#x1f4ab;设计介绍&#x1f4ab;仿真图电动机驱动模块电路设计电源模块电路设计控制按键进水阀和排水阀控制继电器 &#x1f4ab;程序设计main函数 &#x1f4ab;设计报告&#x1f4ab;资料清单&&下载链…

Linux(8):BASH

硬件、核心与 Shell 操作系统其实是一组软件&#xff0c;由于这组软件在控制整个硬件与管理系统的活动监测&#xff0c;如果这组软件能被用户随意的操作&#xff0c;若使用者应用不当&#xff0c;将会使得整个系统崩溃。因为操作系统管理的就是整个硬件功能。 应用程序在最外层…

光线追踪-Peter Shirley的RayTracingInOneWeekend系列教程(book1-book3)代码分章节整理

自己码完了一遍了&#xff0c;把代码分章节整理了一下&#xff0c;可以按章节独立编译&#xff0c;运行, 也可以直接下载编译好的release版本直接运行。 项目地址&#xff1a; Github: https://github.com/disini/RayTracingInOneWeekendChaptByChapt ​ ​ ​ ​

[C/C++]数据结构 堆的详解

一:概念 堆通常是一个可以被看做一棵完全二叉树的数组对象,它是一颗完全二叉树,堆存储的所有元素按完全二叉树的顺序存储方式存储在一个一维数组中,并且需要满足每个父亲结点总小于其子节点(或者每个父亲结点总大于其子节点) 堆可以分为两种: 小堆: 任意一个父亲节点都小于其子…

C++前缀和算法:统计美丽子字符串

题目 给你一个字符串 s 和一个正整数 k 。 用 vowels 和 consonants 分别表示字符串中元音字母和辅音字母的数量。 如果某个字符串满足以下条件&#xff0c;则称其为 美丽字符串 &#xff1a; vowels consonants&#xff0c;即元音字母和辅音字母的数量相等。 (vowels * cons…

大语言模型损失函数详解

我们可以把语言模型分为两类&#xff1a; 自动回归式语言模型&#xff1a;自动回归式语言模型在本质上是单向的&#xff0c;也就是说&#xff0c;它只沿着一个方向阅读句子。正向&#xff08;从左到右&#xff09;预测&#xff1b;反向&#xff08;从右到左&#xff09;预测。…

Elasticsearch:LangChain 是什么?

当你将应用程序称为 “AI&#xff08;人工智能&#xff09;” 时&#xff0c;这通常意味着它包含与学习模型&#xff08;例如大型语言模型&#xff0c;或 LLM&#xff09;的交互。 [不那么]有趣的事实是&#xff0c;LLM 的使用实际上并不是使应用程序变得智能的原因。 它的特殊…

Linux中vi常用命令-批量替换

在日常服务器日志查看中常用到的命令有grep、tail等&#xff0c;有时想查看详细日志&#xff0c;用到vi命令&#xff0c;记录下来&#xff0c;方便查看。 操作文件&#xff1a;test.properites 一、查看与编辑 查看命令&#xff1a;vi 文件名 编辑命令&#xff1a;按键 i&…

【SAS Planet 下载地图瓦片-读取】

SAS Planet下载地图瓦片请看上一篇 详细介绍了下载方法 【SAS Planet 下载地图瓦片】-CSDN博客 准备工作&#xff1a; 1.提前下载好地图瓦片数据 SAS Planet下载地图瓦片默认存储路径如下 默认存储格式为 .sqlitedb 2.提前准备好 java开发环境和开发工具&#xff0c;新建 一个…

印度客户来访广东育菁装备考察桌面型数控机床

印度客户来访广东育菁装备考察桌面型数控机床&#xff0c;这是一个重要的商业活动&#xff0c;对于育菁装备来说&#xff0c;这是一个展示产品和技术实力&#xff0c;拓展国际市场的好机会。 在接待印度客户的过程中&#xff0c;育菁装备需要做好充分的准备&#xff0c;包括&am…

YOLOv8改进 | SAConv可切换空洞卷积(附修改后的C2f+Bottleneck)

论文地址&#xff1a;官方论文地址 代码地址&#xff1a;官方代码地址 一、本文介绍 本文给大家带来的改进机制是可切换的空洞卷积&#xff08;Switchable Atrous Convolution, SAC&#xff09;是一种创新的卷积网络机制&#xff0c;专为增强物体检测和分割任务中的特征提取而…

Linux socket编程(6):IO复用之select原理及例子

文章目录 1 五种I/O模型1.1 阻塞I/O模型1.2 非阻塞I/O模型1.3 I/O复用模型1.4 信号驱动I/O模型1.5 异步I/O模型 2 select函数3 select实战&#xff1a;实现多个套接字监听3.1 客户端3.2 服务端3.3 实验结果3.4 完整代码 在之前的网络编程中&#xff0c;我们遇到了一个问题&…

初识数据结构

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd; 熬过了我们不想要的生活&#xf…

RT-DETR论文阅读笔记(包括YOLO版本训练和官方版本训练)

论文地址&#xff1a;RT-DETR论文地址 代码地址&#xff1a;RT-DETR官方下载地址 大家如果想看更详细训练、推理、部署、验证等教程可以看我的另一篇博客里面有更详细的介绍 内容回顾&#xff1a;详解RT-DETR网络结构/数据集获取/环境搭建/训练/推理/验证/导出/部署 目录 一…