rust 中ref和&区别

在 Rust 中,ref 关键字和 & 符号都与引用(reference)相关,但它们在使用场景和含义上有根本的区别:
  • & (引用符号) 用于创建引用或声明接收引用的类型。
  • ref (关键字) 用于模式匹配(如 let 绑定、for 循环、match 表达式)中,以改变绑定的方式,使其绑定到一个值的引用,而不是直接绑定到值本身。
 
1. & 符号:引用操作符
& 是最常见的创建引用的方式。
  • 创建不可变引用: let r = &value;
  • 创建可变引用: let mr = &mut value;
  • 在函数签名中指定参数类型: fn func(arg: &Type) {}
它是一个表达式操作符,作用于一个值(value)上。
 
2. ref 关键字:模式匹配修饰符
ref 关键字用在赋值(绑定)过程的左侧,即模式(pattern)中。它的作用是告诉编译器:“在这个特定的绑定中,我不想获取值的所有权或拷贝值,我只想得到这个值的引用。”
 
核心区别总结
 
特性& 符号ref 关键字
位置 表达式的右侧(值前面) 模式的左侧(变量名前面)
作用 创建一个新的引用 修改绑定的行为为“按引用绑定”
目的 借用数据 在解构(模式匹配)时避免所有权转移
 
使用场景示例
最能体现区别的场景是 let 绑定和 match 表达式。
 
示例一:let 绑定和解构
假设我们有一个元组 (i32, i32)
let point = (1, 2);

// 使用 & 创建引用(右侧)
let r = &point; 
// r 的类型是 &(i32, i32),它是一个指向 point 的引用。

// 使用 ref 在模式匹配中获取内部元素的引用(左侧)
// 解构 point 元组,并将内部元素的引用绑定到 x 和 y
let (ref x, ref y) = point; 
// x 的类型是 &i32,y 的类型是 &i32。
// 注意:point 的所有权没有被移动。

// 如果不使用 ref,所有权会被移动(如果 point 是可移动类型)或者发生拷贝(i32 是 Copy 类型)
let (x_val, y_val) = point; // 发生拷贝
// x_val 和 y_val 的类型是 i32
示例二:match 表达式
在 match 语句中,如果你想根据一个引用进行匹配,并且在匹配分支中仍然使用引用,你需要同时使用 & 和 ref
 
#[derive(Debug)]
struct Person {
    name: String,
    age: u8,
}

let person = Person { name: String::from("Alice"), age: 30 };

// 匹配一个 &Person 类型的引用
match &person { 
    // 在这里,如果你只写 name,你会得到一个 String 的引用 &String
    // 但如果你使用 ref name,你是在创建一个新的绑定 name,它的类型是 &String
    &Person { ref name, age } => {
        // person 的所有权没有被 move
        println!("匹配到名字: {}", name);
        println!("Age: {}", age);
    }
}
结论
理解这两者的关键在于左右区别:
  • 当你需要创建一个指向已有数据的引用时,使用 &(放在值的右侧表达式中)。
  • 当你需要在解构数据时将绑定方式修改为按引用绑定时,使用 ref(放在模式的左侧变量名前)。

参考资料:

1. ref与&区别

 

posted @ 2025-11-25 10:53  PKICA  阅读(0)  评论(0)    收藏  举报