& 的各种用法
不可变引用(借用)
最基本的形式,用于借用所有权而不转移:
1 2 3 4 5 6 7
| fn print_length(s: &String) { println!("{}", s.len()); }
let s = String::from("hello"); print_length(&s); println!("{}", s);
|
可变引用 &mut
需要修改借用内容时使用,同一时间只能有一个可变引用:
1 2 3 4 5 6
| fn append(s: &mut String) { s.push_str(" world"); }
let mut s = String::from("hello"); append(&mut s);
|
解引用 *
引用存的是地址,* 取值:
1 2 3
| let x = 5; let r = &x; assert_eq!(*r, 5);
|
自动解引用
Rust 会隐式解引用,让代码简洁:
1 2 3 4
| let s = String::from("hello"); let r = &s;
let len = r.len();
|
模式匹配中的引用
不想转移所有权时:
1 2 3 4 5 6
| let v = vec![1, 2, 3];
for &x in &v { println!("{}", x); }
|
for 循环中 & 的智能匹配
Rust 的 for 循环会自动尝试解引用,这是写法的对比:
1 2 3 4 5 6 7 8 9 10 11
| let v = vec![1, 2, 3];
for item in &v { println!("{}", *item); }
for &x in &v { println!("{}", x); }
|
对于可变引用:
1 2 3 4 5 6 7 8 9 10 11 12
| let mut v = vec![1, 2, 3];
for x in &mut v { *x *= 2; }
for &mut x in &mut v { x *= 2; }
|
.iter() vs & 的区别:
1 2 3 4 5 6 7
| for x in v.iter() for x in &v
for x in v.iter_mut() for x in &mut v
|
字面量前加 &
直接在字面量前加 & 创建引用,无需先绑定变量:
1 2 3 4 5 6 7 8
| let r: &i32 = &42;
let s: &&str = &"hello";
let arr: &[i32; 3] = &[1, 2, 3];
|
实用场景:函数参数期望引用时直接传递:
1 2 3 4 5
| fn print_ref(x: &i32) { println!("{}", x); }
print_ref(&100);
|
重要限制:字面量无法获取可变引用 &mut
1 2 3 4 5 6 7
|
let mut x = 42; let r: &mut i32 = &mut x; *r = 100;
|
字符串字面量本身就是 &str(静态生命周期),再 & 就是 &&str:
1 2
| let s1: &str = "hello"; let s2: &&str = &"hello";
|
解构赋值
1 2
| let (x, y) = (&1, &2); let &a = x;
|
闭包捕获
1 2 3 4 5
| let s = String::from("hello");
let f = || println!("{}", &s); f(); println!("{}", s);
|
关键规则
| 规则 | 说明 |
|---|
| 任意数量不可变引用 OR 一个可变引用 | 不能同时拥有 |
| 引用必须有效 | 不能悬垂引用 |
&T 实现 Copy | 引用本身可以复制 |