Rust中的&和ref使用解读

 更新时间:2025年02月26日 11:39:28   作者:许野平  
在Rust中,`&`和`ref`都可以用来定义指针,但它们的使用位置不同,`&`通常放在等号右边,而`ref`放在左边,`&`主要用于函数参数和模式匹配中,而`ref`主要用于模式匹配中,Rust通过`&`和`ref`提供了灵活的指针操作,使得代码更加安全和高效

Rust中的&和ref使

1. & 和 ref 都是用来定义指针的

废话少说,先看代码:

fn main() {
    let mut a: i32 = 111;

    let b = &a;
    println!("{}", *b); //111

    let ref c = a;
    println!("{}", *c); //111
}

而这结果一样,都是在声明一个指针。区别在那里?& 放在等号的右边, ref 放在等好的左边。

在看个例子,看看如何用指针修改变量:

fn main() {
    let mut a: i32 = 111;

    let b = &mut a; // 指针 b 本身是不可以修改的,但它指向的内容是可以修改的。
    *b = 222;
    println!("{}", a); // 222

    let ref mut c = a; // 指针 c 本身是不可以修改的,但它指向的内容是可以修改的。
    *c = 333;
    println!("{}", a); //333
}

在代码行里,二者没有任何区别。但是,为什么弄出两个来呢?

2. 只能用 & 定义指针的地方

看一段代码:

fn foo(x: &mut i32) {
    *x = 999;
}
fn main() {
    let mut a: i32 = 111;
    foo(&mut a);
    println!("{}", a); // 999
}

在函数传参的时候用到了 & 来表示传入参数栈的是一个可修改变量的地址。

下面我们修改一下,改成下面的代码:

fn foo(ref mut x: i32) {
    *x = 999;
}
fn main() {
    let mut a: i32 = 111;
    foo(a);
    println!("{}", a); // 111
}

foo(a) 的调用语义是说,要把 a 的值复制到栈空间,因此,fn foo(ref mut x: i32) 中参数 x 引用的是栈上的数据。也就是说,不管函数的参数 x 如何声明,foo(a) 这种形式传入参数 a,都不可能修改变量 a 的值。我觉得这个规定是合理的,比 C++ 的引用的语义声明简单、合理多了。

我们再修改一下:

fn foo(ref x: &mut i32) {
    **x = 999;
}
fn main() {
    let mut a: i32 = 111;
    foo(&mut a);
    println!("{}", a); // 999
}

这次又成功了。但是这个 **x 你不觉得麻烦吧?因此,在函数参数声明中,一般只用 & 来传入变量的地址。

3. 只能用 ref 定义指针的地方

看下面的代码:

fn main() {
    let s = Some(String::from("Hello!"));
    match s {
        Some(t) => println!("t = {}", t),
        _ => {}
    }
    println!("s = {}", s.unwrap());
}

这个是无法编译的。因为 match s 语句中,已经把 s 的所有权给转移了,导致最后一条语句无法执行。

编译提示如下:

编译期建议在模式匹配中把变量 t 改成 ref t,也就是说把 t 声明成指针即可解决问题。

修改后代码如下:

fn main() {
    let s = Some(String::from("Hello!"));
    match s {
        Some(ref t) => println!("t = {}", t),
        _ => {}
    }
    println!("s = {}", s.unwrap());
}

因为在模式匹配代码块中,我们没有机会声明变量类型,只能用 ref 表示变量 t 是个指针。

我试了一下,不用 ref 的话,还有一个变通的方法,就是把 match s 改成 match &s。

代码如下:

fn main() {
    let s = Some(String::from("Hello!"));
    match &s {
        Some(t) => println!("t = {}", t),
        _ => {}
    }
    println!("s = {}", s.unwrap());
}

这个时候 t 前面加不加 ref 结果都一样。因为 match 只是借用 s,所以不会影响 s 的生命周期。

4. 更多的试验

下面给出了一组代码,我们看看那些是合法的,那些是非法的。

fn main() {
    let v = 123;

    let x: &i32 = &v; 					// OK!
    let x: &i32 = &(123 + 456); 		// OK!
    if let Some(x:&i32) = Some(&123); 	// Error!

    let ref x: i32 = v;					// OK!
    let ref x: i32 = 123 + 456;			// OK!
    if let Some(ref x) = Some(123) {}	// OK!
}

5. 指针变量的解引用

看下面代码,道理我不多讲了,rust 会自动解多层嵌套引用,这个太方便了。

fn main() {
    let a: &i32 = &123;
    let b: &&i32 = &a;
    let c: &&&i32 = &b;

    println!("a = {}, b = {}, c = {}", a, b, c);
    println!("*a = {}, **b = {}, ***c = {}", *a, **b, ***c);
}

/* output
a = 123, b = 123, c = 123
*a = 123, **b = 123, ***c = 123
*/

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Rust中的Drop特性之解读自动化资源清理的魔法

    Rust中的Drop特性之解读自动化资源清理的魔法

    Rust通过Drop特性实现了自动清理机制,确保资源在对象超出作用域时自动释放,避免了手动管理资源时可能出现的内存泄漏或双重释放问题,智能指针如Box、Rc和RefCell都依赖于Drop来管理资源,提供了灵活且安全的资源管理方案
    2025-02-02
  • Rust中的方法与关联函数使用解读

    Rust中的方法与关联函数使用解读

    在Rust中,方法是定义在特定类型(如struct)的impl块中,第一个参数是self(可变或不可变),方法用于描述该类型实例的行为,而关联函数则不包含self参数,常用于构造新实例或提供一些与实例无关的功能,Rust的自动引用和解引用特性使得方法调用更加简洁
    2025-02-02
  • 如何使用VSCode配置Rust开发环境(Rust新手教程)

    如何使用VSCode配置Rust开发环境(Rust新手教程)

    这篇文章主要介绍了如何使用VSCode配置Rust开发环境(Rust新手教程),本文通过图文并茂的形式给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • Rust的泛型、Traits与生命周期用法及说明

    Rust的泛型、Traits与生命周期用法及说明

    本文通过一个寻找列表中最大值的示例,展示了如何从重复代码中提取函数,再利用泛型实现代码复用,主要步骤包括:识别重复逻辑;抽象提取;泛型应用;进一步扩展,通过不断抽象和泛化,我们不仅能减少代码重复,还能写出更通用、健壮和可维护的代码
    2025-02-02
  • Rust语言之trait中的个方法可以重写吗

    Rust语言之trait中的个方法可以重写吗

    在Rust中,trait定义了一组方法,这些方法可以被一个或多个类型实现,当你为某个类型实现一个trait时,你可以为该trait中的每个方法提供自己的具体实现,本文将给大家介绍一下trait中的个方法是否可以重写,需要的朋友可以参考下
    2023-10-10
  • Rust 枚举的使用学习笔记

    Rust 枚举的使用学习笔记

    Rust中的枚举是一种用户定义的类型,本文主要介绍了Rust枚举的使用,它们不仅仅用于表示几个固定的值,还可以包含函数和方法,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • 详解Rust中泛型的使用

    详解Rust中泛型的使用

    泛型是一种在编写代码时不指定具体类型,而在使用时再确定类型的编程技巧,本文将详细介绍 Rust 中泛型的相关概念和用法,希望对大家有所帮助
    2023-06-06
  • Rust中用enum实现多参数Hook机制完整代码

    Rust中用enum实现多参数Hook机制完整代码

    在 Rust 中,如果想为enum实现一个带多参数的 Hook 机制,可以结合模式匹配和枚举来处理,这种方式可以扩展到支持不同类型的输入参数和逻辑处理,下面通过示例代码介绍Rust中用enum实现多参数Hook机制,感兴趣的朋友一起看看吧
    2024-12-12
  • Rust你不认识的所有权

    Rust你不认识的所有权

    所有权对大多数开发者而言是一个新颖的概念,它是 Rust 语言为高效使用内存而设计的语法机制。所有权概念是为了让 Rust 在编译阶段更有效地分析内存资源的有用性以实现内存管理而诞生的概念
    2023-01-01
  • Rust之智能指针的用法

    Rust之智能指针的用法

    在Rust中,智能指针是管理内存所有权和生命周期的核心工具,本文主要介绍了Rust之智能指针的用法,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03

最新评论