Rust 模式匹配中的 和 ref

news/2024/9/23 20:14:44/

一、Rust & 和 ref

1.Rust的ref有什么用

根据Rust官方文档https://doc.rust-lang.org/std/keyword.ref.html

Rust ref 主要用在模式匹配match的所有权问题中。

ref在 Rust中,也是声明一个指针类型变量,进一步说明ref和&在其它方面区别,我们下一篇再说。

Rust的模式匹配,可以发生在函数参数match

  1. 函数参数
rust">fn foo(x: String) {//String::from("test")的所有权已经移交给了xprintln!("{}",x);// 代码
}fn main() {let mut s=String::from("test");foo(s);println!("{}",s);//s的所有权已经丢失,所以不能使用了,此处出错
}

特别注意一下,函数传参也会交出所有权
2.match

rust">fn main() {let x = String::from("test");match x {y => println!("{}", y),// String::from("test")的所有权移动给了y_ => println!("Default case, x = {:?}", x),}println!("at the end: x = {:?}", x);//x的所有权已经丢失,不能再使用。
}

特别注意一下,match的模式匹配是会交出所有权的。

除了使用&引用借用来避免交出所有权的问题,在模式匹配中,我们可以使用**&或ref**来避免交出所有权,match中的ref不再遵循借用规则。那么前面的代码我们可以修改为。

  1. 函数参数使用**&避免**交出所有权
rust">fn foo(x: &mut String) {//println!("{}",x);// 代码
}fn main() {let mut s=String::from("test");foo(&mut s);//(可变/不可变)引用,不拥有所有权println!("{}",s);
}

代码运行通过

    Finished release [optimized] target(s) in 0.20sRunning `target/release/world_hello`
test
test

2、match使用ref避免交出所有权

rust">fn main() {let x = String::from("test");match x {ref y => println!("{}", y),// 其实在match中,不是定义一个变量,而是声明一个变量,ref是进一步声明,y是一个引用,但是不能够&y,因为我们不能够在match中声明y的具体类型。_ => println!("Default case, x = {:?}", x),}println!("at the end: x = {:?}", x);
}

代码运行通过

    Finished release [optimized] target(s) in 0.20sRunning `target/release/world_hello`
test
test

其实这里你可能会问,为什么在match中,不使用&借用避免所有权移动的问题,这是因为match本身机制导致的。

在match中,我们没有机会声明变量类型,不能用&修饰匹配的变量

当然,你非要在**match使用&**来避免移交所有权的问题,我们可以这样做

rust">fn main() {let x = String::from("test");match &x {//将引用定义在这里y => println!("{}", y),//这里不能够写成&y => println!("{}", y),_ => println!("Default case, x = {:?}", x),}println!("at the end: x = {:?}", x);
}

代码运行也是成功的

    Finished release [optimized] target(s) in 0.22sRunning `target/release/world_hello`
test
at the end: x = "test"

我们再来看一个骚的

rust">
// 修复错误,尽量少地修改代码
// 不要移除任何代码行
fn main() {let mut v = String::from("hello,");let r = &mut v;match r {&mut value => value.push_str(" world!") }
}

前面我们说了 ,我们不能声明匹配变量,也就是value,那么**&mut 是肯定不能用**的,其实第一版修改,我们可以改成

rust">
// 修复错误,尽量少地修改代码
// 不要移除任何代码行
fn main() {let mut v = String::from("hello,");let r = &mut v;match r {value => value.push_str(" world!") //这样其实value就是可变引用,但是&mut v本身的所有权被value拿走了}
}

根据代码注释,如果我们稍加修改就会发现问题

rust">
// 修复错误,尽量少地修改代码
// 不要移除任何代码行
fn main() {let mut v = String::from("hello,");let r = &mut v;match r {value => value.push_str(" world!") }println!("{}",r);
}

运行代码

error[E0382]: borrow of moved value: `r`--> src/main.rs:11:17|
6  |   let r = &mut v;|       - move occurs because `r` has type `&mut String`, which does not implement the `Copy` trait
...
9  |      value => value.push_str(" world!") |      ----- value moved here
10 |   }
11 |   println!("{}",r);|                 ^ value borrowed here after move

这里说了,&mut v的所有权被value拿走了

那我不想被value拿走,我们应该怎么做,那么这时候ref的作用就来了,我们可以这么修改

rust">// 修复错误,尽量少地修改代码
// 不要移除任何代码行
fn main() {let mut v = String::from("hello,");let r = &mut v;match *r {//注意这里是*r,因为r本身就是&str,如果传下去r,ref r 就变成了双重引用,不符合题意ref mut value => value.push_str(" world!") //此时value就是&str类型,但是这不是引用类型}println!("{}",r);
}

运行代码

    Finished release [optimized] target(s) in 0.34sRunning `target/release/world_hello`
hello, world!

前面我们说了,ref不遵循借用的那一套规则,所以上面的代码是可以运行成功的。

按照正常思路的话(假设),按道理应该是两个可变引用,是违背借用原则的,会不会是match{}框住了value的作用域导致,其实只有一个可变引用?

那我们在看一段代码

rust">
// 修复错误,尽量少地修改代码
// 不要移除任何代码行
fn main() {let mut v = String::from("hello,");let r = &mut v;match *r {ref mut value => {value.push_str(" world!") ;println!("{}",r);}}println!("{}",r);
}

运行一下

    Finished release [optimized] target(s) in 0.21sRunning `target/release/world_hello`
hello, world!
hello, world!

哈哈,我们已经验证完了

ref不遵循借用的那一套规则,在match的模式匹配中,ref也可以是不拿所有权的一种引用方法。


http://www.ppmy.cn/news/1430732.html

相关文章

AI重建粒子轨迹,发现新物理学

目录 二Sora冲击还没来,但智能家居人已经开始焦虑了! 一、智能家居新革命:AIoH 二、AI技术接入智能家居,未来价值几何? 三、AI 智能家居,不是纸上谈兵 四、结语 电子学在核物理领域从来都不是一帆风顺…

【Linux】权限(shell运行原理、概念,Linux权限)

🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12625432.html 目录 shell命令以及运行原理 创建和删除用户 创建新普通用户 删除用户 Linux权…

知道做到 一篇总结学习方法的笔记

元数据 [!abstract] 知道做到:跃迁式学习 书名: 知道做到:跃迁式学习作者: 彼得•霍林斯简介: 学习是改善你的生活环境、成为你想成为的人的关键。科学的方法能加速学习进程,让你事半功倍。技能、信息和能力…

Docker搭建NetbootXYZ

NetbootXYZ Docker 镜像功能介绍 NetbootXYZ 是一个开源的 PXE 引导服务器,用于网络引导操作系统安装。它支持多种操作系统的网络安装,如 Ubuntu、Debian、Windows 等。NetbootXYZ 提供了一个 Web 界面来管理网络引导过程,包括设置网络启动选…

[大模型]Qwen-7B-Chat WebDemo

Qwen-7B-Chat WebDemo 环境准备 在autodl平台中租一个3090等24G显存的显卡机器,如下图所示镜像选择PyTorch–>2.0.0–>3.8(ubuntu20.04)–>11.8 接下来打开刚刚租用服务器的JupyterLab,并且打开其中的终端开始环境配置、模型下载和运行demo…

类似nohup在windows通过cmd后台运行进程方法

Linux后台运行进程时,通常使用如下方法: nohup "运行的内容" &windows相应功能的命令行如下(此方法进程有页面,可能会在桌面展示,关闭窗口后进程消失。 call start /min "n" "运行的内容"cmd…

IntelliJ IDEA 2024 中文激活版 mac/win

IntelliJ IDEA 2024是一款由JetBrains公司开发的集成开发环境(IDE),专为Java等编程语言量身打造,同时支持多种其他语言。该软件凭借其出色的智能化和高效性,赢得了广大开发者的喜爱。 IntelliJ IDEA 2024 for mac中文激…

基于JavaWeb手工艺品购物系统的设计与实现

1、系统演示视频(演示视频) 2、需要请联系