- 使用
RefCell
实现:
use std::cell::RefCell;
struct Person {
name: String,
age: u32,
}
fn modify_person(person: &RefCell<Person>) {
// 不可变借用读取name
let name = person.borrow().name.clone();
println!("Name: {}", name);
// 可变借用修改age
let mut person_mut = person.borrow_mut();
person_mut.age += 1;
}
fn main() {
let person = RefCell::new(Person {
name: "Alice".to_string(),
age: 30,
});
modify_person(&person);
println!("Age after modification: {}", person.borrow().age);
}
- 原理:
RefCell
允许在运行时进行借用检查,而不是编译时。
borrow
方法获取不可变借用,borrow_mut
方法获取可变借用。在运行时,RefCell
会跟踪当前是否有不可变或可变借用正在使用。如果违反借用规则(如在有不可变借用时尝试获取可变借用),会在运行时panic
。但只要程序逻辑正确,就可以实现在同一作用域内先不可变借用再可变借用的操作。
- 使用
Cell
实现(如果name
是Copy
类型):
use std::cell::Cell;
struct Person {
name: char, // 假设name是Copy类型,这里用char举例
age: Cell<u32>,
}
fn modify_person(person: &Person) {
// 读取name
let name = person.name;
println!("Name: {}", name);
// 修改age
person.age.set(person.age.get() + 1);
}
fn main() {
let person = Person {
name: 'A',
age: Cell::new(30),
};
modify_person(&person);
println!("Age after modification: {}", person.age.get());
}
- 原理:
Cell
适用于内部类型实现了Copy
trait的情况。
Cell
提供get
和set
方法来读取和修改内部值。它通过内部可变性,允许在不可变引用的情况下修改内部值。因为内部类型是Copy
的,所以读取值时不会产生借用,也就不存在借用冲突问题,从而可以实现先读取再修改的操作。