学习 Rust 的第七天:如何理解引用

devtools/2024/12/22 2:39:08/

大家好,

今天是我学 Rust 的第7天,今天我要来看一下引用和借用。昨天我学习了 Rust 的所有权模型,如果你对 Rust 一无所知的话,那篇文章是必读的。

引用

昨天我们看到,将参数传递给函数与将值赋给另一个变量产生了相同的效果,实际上导致了所有权的丧失。不过,有一个解决方法。
如果你了解 C 语言,指针 是 C 语言的一个重要概念。而引用与之类似。

让我们看一下代码并理解它:

rust">fn main(){  let s1: String = String::from("Hello World");  let length: usize = calculate_length(&s1); // & 用于传递字符串的引用  println!("`{}` 的长度为 {}" ,s1,length);  
}  fn calculate_length(s: &String) -> usize {  s.len()  }

Rust 中的引用是指针,允许借用和访问数据而不转移所有权,有助于内存安全,防止数据竞争。

解释:

  • fn main(): 程序的入口点。
  • let s1: String = String::from("Hello World");: 声明一个 String 变量 s1,值为 “Hello World”。
  • let length: usize = calculate_length(&s1);: 调用 calculate_length 函数,传递对字符串 s1 的引用。
  • fn calculate_length(s: &String) -> usize: 函数以对 String 的引用 (&String) 作为参数,并返回它的长度作为 usize 类型。
  • s.len(): 获取引用 s 所指向的 String 的长度。
  • println!("{} 的长度为 {}" ,s1, length);: 打印原始字符串 s1 及其长度。

关键概念:

  • & 用于传递对字符串的引用 (&s1),而不是转移所有权,防止字符串被移动或克隆。
  • 这种借用允许 calculate_length 函数在不获取所有权的情况下操作字符串。
  • 引用默认为不可变。

感谢 Let's Get Rusty 在他的 YouTube 频道上提供这么棒的解释。

可变引用

我们上面看到的是不可变引用,我们无法真正改变值,但我们可以从中读取。让我们来看看 可变引用

rust">fn main() {  let mut s1 = String::from("Hello");  // 传递可变引用给 modify_string 函数  modify_string(&mut s1);  // 原始字符串现在被修改了  println!("修改后的字符串: {}", s1);  
}  fn modify_string(s: &mut String) {  s.push_str(", World!"); // 通过追加来修改字符串  
}

解释:

  • fn main(): 程序的入口点。
  • let mut s1 = String::from("Hello");: 声明一个可变的 String 变量 s1
  • modify_string(&mut s1);: 调用 modify_string 函数,传递对 s1 的可变引用。
  • fn modify_string(s: &mut String): 函数以对 String 的可变引用 (&mut String) 作为参数。
  • s.push_str(", World!");: 通过追加将 “, World!” 添加到 s 所指向的字符串。
  • println!("修改后的字符串: {}", s1);: 打印修改后的字符串。

关键概念:

  • 可变引用可以通过 &mut 变量名 进行传递。

可变引用的规则

  • 对于特定数据片段,只允许一个可变引用或多个不可变引用。
  • 在可变引用有效时,不允许对相同数据进行其他引用。
  • 可变引用受其作用域的约束,防止悬空引用。
  • 在特定作用域内只能存在一个可变引用,以确保协调的修改。

简单来说,一个特定作用域内只能存在一个对变量的可变引用。

虽然不可变引用的数量可以是无限的。

但是,不可变和可变引用可以同时存在于相同的作用域内。

示例:

rust">fn main(){  let mut string1: String = String::from("Hello World");  let reference1: &String = &string1;  let reference2: &String = &string1;  takes_ownership(reference1);  takes_ownership(reference2);  let _mut_ref: &mut String = &mut string1;  
}  fn takes_ownership(_r1: &String){  
}

这个例子完全没问题,因为在我们创建 _mut_ref 时,reference1reference2 已经超出了作用域。

rust">// 这段代码会导致错误  
fn main(){  let mut string1: String = String::from("Hello World");  let reference1: &String = &string1;  let reference2: &String = &string1;  // 因为这一行  let _mut_ref: &mut String = &mut string1;  takes_ownership(reference1);  takes_ownership(reference2);  }  fn takes_ownership(_r1: &String){  
}

结论

学习 Rust 的旅程中,第7天探讨了引用和借用,这是内存安全的基本概念。不可变引用允许在不转移所有权的情况下读取数据,而可变引用则允许修改,但必须遵守规则以确保独占访问和防止数据


http://www.ppmy.cn/devtools/4180.html

相关文章

【C语言】指针详解(五)

目录 1.字符指针 1.1常量字符串 2.指针数组 3.数组指针 1.字符指针 字符指针就是指向字符的指针,字符指针可以存储字符变量的地址。 举例如下: 定义指针变量pa存a的地址,改变*pa的值,a也会随之改变 。 1.1常量字符串 &#x1f…

C# WPF故障记录

1,ComboBox初始更新问题 问题描述:初始化时,设置了SelectIndex,但是尚未正常显示 解决办法:IsEditable"False" 2,Window中创建的Task无法正常退出问题 问题描述:在Window界面文件中添加了Task,但是关闭窗…

【STL详解 —— list的介绍及使用】

STL详解 —— list的介绍及使用 list的介绍list的介绍使用list的构造list iterator的使用list capacitylist element accesslist modifiers 示例list的迭代器失效 list的介绍 list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭…

C语言转型之路:从C到C++的类与对象初探

欢迎来CILMY23的博客 本篇主题为 C语言转型之路:从C到C的类与对象初探 个人主页:CILMY23-CSDN博客 个人专栏系列: Python | C语言 | 数据结构与算法 | C 感谢观看,支持的可以给个一键三连,点赞关注收藏。 写在前头…

JVM(Java虚拟机)内存管理基础理论

JVM(Java虚拟机)内存管理是Java开发和性能优化中的一个核心领域。理解JVM的内存结构和管理机制对于编写高效的Java程序和进行有效的性能调优非常重要。以下是一个关于JVM内存学习的大纲,涵盖了从基础知识到高级主题的各个方面: 1.…

【御控物联】物联网数据传输数据格式

随着物联网技术的快速发展,越来越多的系统和设备被接入到了物联网管理中,数据交换与共享成为了一个重要的问题。不同的设备和系统之间存在着各种各样的通信协议和数据格式,这就给数据获取、交换和共享带来了很大的不便利。 MQTT 是机器对机器…

TCP/IPv4 开发过程中不要开启VPN

问题背景 在通过TCP/IPv4与一个开发板进行通讯的时候,同时开启了VPN,然后就导致一直通讯不上。 问题分析 开启VPN会导致与开发板通讯失败的原因通常是因为VPN会改变你的网络路由。当你连接到VPN时,你的所有或部分网络流量会被重定向到VPN服…

Python基于深度学习的车辆特征分析系统

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…