场景一:拥有结构体变量 t: T,想获取 T 的两个字段的引用
代码:
rust
struct Foo {
pub a: i32,
pub b: u32,
}
fn main() {
let foo = Foo { a: 1, b: 2 };
let a_p = &foo.a;
let b_p = &foo.b;
println!("a: {}, b: {}", a_p, b_p);
}
可以直接使用 &foo.a 的语法获取结构体中字段的引用。
场景二:拥有结构体变量 t: T,想获取 T 的两个字段的可变引用
代码:
rust
struct Foo {
pub a: i32,
pub b: u32,
}
fn main() {
let mut foo = Foo { a: 1, b: 2 };
{
let a_mut = &mut foo.a;
let b_mut = &mut foo.b;
*a_mut += 1;
*b_mut += 1;
}
let p = &foo;
println!("a: {}, b: {}", p.a, p.b);
}
可以使用 &mut foo.a 的语法获取结构体中字段的可变引用,而且还可以同时获得同一结构体变量的另一个字段的可变引用(不违反对同一变量的可变引用不能同时存在)。
在持有可变引用时,想修改变量需使用 *p = 的语法
场景三:拥有变量 t: T 的不可变引用,想获取 T 的两个字段的引用
代码:
rust
struct Foo {
pub a: i32,
pub b: u32,
}
fn main() {
let foo = Foo { a: 1, b: 2 };
let p = &foo;
let a = p.a; // 等价于 let a = (*p).a; 编译器会自动解引用
let b = &p.b;
println!("a: {}, b: {}", a, b);
}
引用使用起来就像直接持有了变量。
场景四:拥有 Guard 变量 p: guard<T>,想获取 T 的两个字段的可变引用
代码(错误示范):
rust
use spin::Mutex;
struct Foo {
pub a: i32,
pub b: u32,
}
fn main() {
let foo = Mutex::new(Foo { a: 1, b: 2 });
{
let mut foo: spin::MutexGuard<'_, Foo> = foo.lock();
let a_mut = &mut foo.a;
let b_mut = &mut foo.b;
*a_mut += 1;
*b_mut += 1;
}
let p = foo.lock();
println!("a: {}, b: {}", p.a, p.b);
}
/// 编译结果
error[E0499]: cannot borrow `foo` as mutable more than once at a time
--> src/main.rs:12:26
|
11 | let a_mut = &mut foo.a;
| --- first mutable borrow occurs here
12 | let b_mut = &mut foo.b;
| ^^^ second mutable borrow occurs here
13 | *a_mut += 1;
| ----------- first borrow later used here
For more information about this error, try `rustc --explain E0499`.
此时不能使用与场景二同样的代码。虽然 foo: MutexGuard 实现了 Deref trait 以便被当作普通引用使用(当执行 foo.a 时,实际上发生的是 (*foo.deref()).a,或者考虑到可变性,发生的是 (*foo.deref_mut()).a 以先获取 mut Foo)。在加入了 deref() 的一步后,编译器就无法判定你最终获取的两个可变引用是否重叠了。