Rust Tips
& 的各种用法
先看 & 所在的位置,再判断含义;不要只把它记成“引用”。Rust 中最常见的四种情况如下。
| 位置 | 写法 | 一句话理解 |
|---|---|---|
| 类型 | &T、&mut T | 这个位置需要一个引用 |
| 表达式前 | &value、&mut value | 从值创建引用,即借用 |
| 模式中 | let &x = r | 匹配引用,并取出其中的值 |
| 两个值之间 | a & b | 按位与运算 |
最实用的判断法:: 右侧通常在写类型,= 右侧通常在写表达式。
1 | |
速查:我现在该写哪个?
| 目的 | 写法 | 所有权结果 |
|---|---|---|
| 只读地传入数据 | 参数写 &T,调用写 &value | 不转移所有权 |
| 修改调用方的数据 | 参数写 &mut T,调用写 &mut value | 不转移所有权,独占访问 |
| 通过引用读出值 | *reference | 访问指向的值 |
| 遍历但保留集合 | for item in &items | 逐项得到 &T |
| 遍历并修改集合 | for item in &mut items | 逐项得到 &mut T |
| 消费集合 | for item in items | 逐项得到 T,集合被移动 |
1. 类型中的 &T 与 &mut T
&T 表示不可变引用:可以读取,不能通过它修改值。&mut T 表示可变引用:可以读取和修改。它们常见于函数参数、返回值、变量标注和方法接收者。
1 | |
&self 是 self: &Self 的简写;&mut self 是 self: &mut Self 的简写。Self 表示当前实现的类型,因此上例分别等价于 self: &Counter 和 self: &mut Counter。
常见类型可按“引用谁”阅读:
| 写法 | 读法 |
|---|---|
&str | 对字符串切片的引用 |
&[T] | 对 T 切片的引用 |
&dyn Trait | 对 trait 对象的引用 |
&&str | 对 &str 的引用 |
&'a T | 有效期至少覆盖 'a 的 T 引用 |
2. 值前的 &value:创建不可变引用
表达式前的 & 执行借用操作。它从已有值创建引用,而不是复制值,也不转移所有权。
1 | |
调用处的 &text 创建引用;参数 text: &str 接收引用。String 会自动解引用为 str,因此函数应优先接收更通用的 &str,而不是 &String。
可以同时存在多个不可变引用:
1 | |
3. 值前的 &mut value:创建可变引用
&mut 创建可变引用。可变引用存在期间,原值不能再被其他引用访问:同一时刻要么有多个只读引用,要么有一个可变引用。
1 | |
需要通过可变引用修改基本类型或集合元素时,用 * 访问它指向的位置:
1 | |
4. *reference:访问引用指向的值
* 是解引用运算符。& 创建或描述引用,* 沿着已有引用访问其指向的值。
1 | |
方法调用会自动完成必要的借用或解引用,因此通常不必手写 (*number_ref).method()。但给引用指向的位置赋值时,必须显式写 *,如上一节的 *score_ref += 1。
5. 模式中的 &pattern:拆开引用
在 let、match、if let 和 for 左侧,& 属于模式。它要求待匹配的值是一个引用,并把其中的值匹配给变量。
1 | |
这里 number_ref 的类型是 &i32,value 的类型是 i32。这需要被取出的值实现 Copy;不能用它从 &String 中移出 String 的所有权。
循环中最常见的组合是:右侧借用集合,左侧拆开元素引用。
1 | |
若要直接使用元素引用,不要在左侧写 &:
1 | |
6. &collection、&mut collection 与迭代
在 for 右侧,&collection 和 &mut collection 是借用表达式;标准集合为它们实现了迭代,因此可作为 .iter() 和 .iter_mut() 的简洁写法。
| 写法 | 等价的常见写法 | 每轮得到 | 集合之后可用? |
|---|---|---|---|
for x in &values | values.iter() | &T | 可以 |
for x in &mut values | values.iter_mut() | &mut T | 可以 |
for x in values | values.into_iter() | T | 通常不可以 |
修改元素时,循环变量本身是 &mut T,再用 * 修改元素:
1 | |
7. 字面量前的 &
字面量也能直接借用,无需先绑定变量。常用于立即满足函数的引用参数。
1 | |
字符串字面量的类型本来就是 &'static str,所以 "hello" 已经是引用;&"hello" 的类型才是 &&str。
8. 两个值之间的 a & b:按位与
当 & 位于两个表达式之间,它不是借用,而是按位与。布尔逻辑与应写 &&。
1 | |
最后再记一次
| 看到的形式 | 应这样理解 |
|---|---|
fn f(x: &T)、let x: &T | 需要或声明引用类型 |
&x、&mut x | 从值创建不可变或可变引用 |
*x | 访问引用指向的值 |
let &x = r、for &x in iter | 在模式中拆开引用 |
for x in &items | 借用集合并遍历 &T |
a & b | 按位与 |






