面试题答案
一键面试struct Person {
name: String,
age: u32,
}
fn main() {
let mut person = Person {
name: String::from("Alice"),
age: 30,
};
// 获取不可变引用
let name_ref = &person.name;
// 获取可变引用前需要先释放不可变引用
// 这里注释掉下面获取可变引用的代码会导致编译错误,因为在同一作用域内不能同时存在不可变和可变引用
// let age_mut_ref = &mut person.age;
// 为了避免错误,可以先使用完不可变引用,再获取可变引用
drop(name_ref);
let age_mut_ref = &mut person.age;
*age_mut_ref = 31;
}
编译错误原因
Rust的借用规则规定,在同一作用域内,不能同时存在对同一数据的可变引用和不可变引用。这是为了防止数据竞争(data race),因为可变引用允许修改数据,而不可变引用允许读取数据,如果两者同时存在,可能会导致读取到不一致的数据。
修改方式
- 先后获取引用:先使用完不可变引用,再获取可变引用。如上述代码中,通过
drop(name_ref)
手动释放不可变引用,然后再获取可变引用。 - 分离作用域:将不可变引用和可变引用的使用放在不同的作用域内,这样在同一时刻只有一种引用存在。例如:
struct Person {
name: String,
age: u32,
}
fn main() {
let mut person = Person {
name: String::from("Alice"),
age: 30,
};
{
let name_ref = &person.name;
// 使用name_ref
}
let age_mut_ref = &mut person.age;
*age_mut_ref = 31;
}
这里不可变引用name_ref
的作用域被限制在花括号内,当离开这个作用域时,name_ref
被释放,此时可以安全地获取可变引用age_mut_ref
。