Rust 所有权模型中的借用规则
- 不可变借用:
fn main() {
let s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} {}", r1, r2);
}
- 这是因为不可变借用只是读取数据,多个读取操作不会相互冲突。
- 可变借用:
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
// 下面这行代码会报错,因为同一时间不能有第二个可变借用
// let r2 = &mut s;
*r1 = String::from("world");
println!("{}", r1);
}
- 不可变借用与可变借用的混合限制:
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
// 下面这行代码会报错,因为已经有了可变借用r1
// let r2 = &s;
*r1 = String::from("world");
println!("{}", r1);
}
- 反过来,当存在不可变借用时,也不能创建可变借用。例如:
fn main() {
let mut s = String::from("hello");
let r1 = &s;
// 下面这行代码会报错,因为已经有了不可变借用r1
// let r2 = &mut s;
println!("{}", r1);
}
为什么要有这些规则
- 内存安全:这些规则确保在任何时刻,对于一块内存只有一个可变引用(可变借用),从而避免数据竞争。数据竞争会导致未定义行为,例如多个线程同时读写同一块内存且至少有一个是写操作,Rust通过借用规则在编译期就杜绝了这种情况。
- 可预测性:规则使得代码行为更具可预测性。开发人员可以明确知道在某一时刻数据是否可以被修改,提高了代码的可读性和维护性。
违反借用规则时编译器的错误提示
- 同一时间多个可变借用:
fn main() {
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
}
error[E0499]: cannot borrow `s` as mutable more than once at a time
--> src/main.rs:4:14
|
3 | let r1 = &mut s;
| - first mutable borrow occurs here
4 | let r2 = &mut s;
| ^^^^^^ second mutable borrow occurs here
5 | }
| - first borrow ends here
- 可变借用与不可变借用冲突:
fn main() {
let mut s = String::from("hello");
let r1 = &s;
let r2 = &mut s;
}
error[E0502]: cannot borrow `s` as mutable because it is also borrowed as immutable
--> src/main.rs:4:14
|
3 | let r1 = &s;
| - immutable borrow occurs here
4 | let r2 = &mut s;
| ^^^^^^ mutable borrow occurs here
5 | }
| - immutable borrow ends here