Rust Tips
& 的各种用法
1. 不可变引用(借用)
最基本的形式,用于借用所有权而不转移:
fn print_length(s: &String) {
println!("{}", s.len());
} // s 在这里归还,不影响原数据
let s = String::from("hello");
print_length(&s);
println!("{}", s); // 还能用2. 可变引用 &mut
需要修改借用内容时使用,同一时间只能有一个可变引用:
fn append(s: &mut String) {
s.push_str(" world");
}
let mut s = String::from("hello");
append(&mut s);3. 解引用 *
引用存的是地址,* 取值:
let x = 5;
let r = &x;
assert_eq!(*r, 5); // 解引用得到值4. 自动解引用
Rust 会隐式解引用,让代码简洁:
let s = String::from("hello");
let r = &s;
// 等价于 (*r).len()
let len = r.len();5. 模式匹配中的引用
不想转移所有权时:
let v = vec![1, 2, 3];
// 不获取所有权,只借用
for &x in &v {
println!("{}", x);
}
// v 还能用for 循环中 & 的智能匹配
Rust 的 for 循环会自动尝试解引用,这是写法的对比:
let v = vec![1, 2, 3];
// 方式1: item 是 &i32
for item in &v {
println!("{}", *item); // 需要显式解引用
}
// 方式2: 使用 &x 模式,直接得到 i32
for &x in &v {
println!("{}", x); // x 已经是 i32
}对于可变引用:
let mut v = vec![1, 2, 3];
// 修改元素
for x in &mut v {
*x *= 2; // 必须显式解引用才能修改
}
// 或者用 &mut 模式解构
for &mut x in &mut v {
x *= 2; // x 是 i32,但不能这样修改原值!
}
// 注意:&mut x 解构后得到的 x 是副本,修改不影响原数组.iter() vs & 的区别:
// 这两者是等价的
for x in v.iter() // 显式调用 iter()
for x in &v // 隐式调用 iter()
// 这两者也等价
for x in v.iter_mut()
for x in &mut v6. 字面量前加 &
直接在字面量前加 & 创建引用,无需先绑定变量:
// 引用整数
let r: &i32 = &42;
// 引用字符串字面量
let s: &&str = &"hello";
// 引用数组
let arr: &[i32; 3] = &[1, 2, 3];实用场景:函数参数期望引用时直接传递:
fn print_ref(x: &i32) {
println!("{}", x);
}
print_ref(&100); // 直接传字面量引用,无需 let x = 100;重要限制:字面量无法获取可变引用 &mut
// 编译错误!字面量是临时值,无法修改
// let r: &mut i32 = &mut 42;
// 正确做法:先绑定到可变变量
let mut x = 42;
let r: &mut i32 = &mut x;
*r = 100;字符串字面量本身就是 &str(静态生命周期),再 & 就是 &&str:
let s1: &str = "hello"; // 字符串切片,类型 &str
let s2: &&str = &"hello"; // 对字符串切片的引用7. 解构赋值
let (x, y) = (&1, &2);
let &a = x; // a = 17. 闭包捕获
let s = String::from("hello");
// 闭包借用 s,不转移所有权
let f = || println!("{}", &s);
f();
println!("{}", s); // s 还在关键规则
| 规则 | 说明 |
|---|---|
| 任意数量不可变引用 OR 一个可变引用 | 不能同时拥有 |
| 引用必须有效 | 不能悬垂引用 |
&T 实现 Copy | 引用本身可以复制 |

