Rust中的可变引用(存在一些问题)
示例程序:
fn main() {
let mut s = String::from("hello");
make_yuyoubei(&mut s);
println!("{}", s); // 输出 yuyoubei
}
fn make_yuyoubei(s: &mut String) {
*s = String::from("yuyoubei");
}
使用使用 &mut
来修饰函数调用时的可变引用;函数声明时也需要 &mut
来修饰函数类型。
不能在同一作用域中对同一个变量声明两个或多个可变引用
例如下面的程序是错误的:
fn main() {
let mut s = String::from("yuyoubei");
let r1 = &mut s;
let r2 = &mut s;
println!("r1 = {}, r2 = {}", r1, r2);
}
会提示出错:
error[E0499]: cannot borrow `s` as mutable more than once at a time
--> src\main.rs:5:14
|
4 | let r1 = &mut s;
| ------ first mutable borrow occurs here
5 | let r2 = &mut s;
| ^^^^^^ second mutable borrow occurs here
6 |
7 | println!("r1 = {}, r2 = {}", r1, r2);
| -- first borrow later used here
在Rust中使用这条限制性规则(即同一作用域中不能对同一变量声明两个可变引用)可以有效避免数据竞争。
数据竞争(data race) 会在指令满足如下 \(3\) 个条件时发生:
- 两个或两个以上的指针同时访问同一空间;
- 其中至少有一个指针会向空间中写入数据;
- 没有同步数据访问的机制。
不能在拥有不可变引用的同时创建可变引用
例如下面的程序时错的:
fn main() {
let mut s = String::from("yuyoubei");
let r1 = &s;
println!("r1 = {}", r1); // 正确,输出 r1 = yuyoubei
let r2 = &s;
println!("r2 = {}", r2); // 正确,输出 r2 = yuyoubei
let r3 = &mut s;
println!("r3 = {}", r3); // 错误!
}
一些问题
虽然书上说有问题,但是实际我是可以正常运行的,运行结果:
r1 = yuyoubei
r2 = yuyoubei
r3 = yuyoubei
也就是说我这个程序不光能编译,还能够正常运行。也就是说程序原本第11行注释“错误!”前面地内容,我是能够正确运行的。
所以我也不确定 不能在拥有不可变引用的同时创建可变引用 这一点目前是否仍然成立。因为书本对应的Rust版本是Rust 2018,而我使用的Rust版本是 Rust 1.58.0(Rust 2021)。