RefCell 是「内部可变性」的代表:借用规则不变,只是检查从编译期搬到了运行期。这篇验证它能做什么、违反规则时会怎样、与编译期借用的对照,以及典型的 Rc
源码:
1 | use std::cell::RefCell;
2 | fn main() {
3 | let c = RefCell::new(vec![1, 2, 3]); // 注意:c 不是 mut
4 | c.borrow_mut().push(4); // 通过共享引用修改
5 | println!("{:?},长度 {}", c.borrow(), c.borrow().len());
6 | {
7 | let r1 = c.borrow(); let r2 = c.borrow(); // 多个不可变借用:可以
8 | println!("同时两个 borrow():{} {}", r1.len(), r2.len());
9 | }
10 | }
编译:成功
运行(退出码 0):
[1, 2, 3, 4],长度 4
同时两个 borrow():4 4 编译:成功
运行(退出码 101):
持有一个 borrow() 时再 borrow_mut() ...
thread 'main' (6994266) panicked at <实验目录>/src/u32b.rs:6:15:
RefCell already borrowed
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
源码:
1 | use std::cell::RefCell;
2 | fn main() {
3 | let c = RefCell::new(5);
4 | let _w1 = c.borrow_mut();
5 | println!("try_borrow_mut() 在已有可变借用时:{:?}", c.try_borrow_mut().is_err());
6 | println!("try_borrow() 在已有可变借用时:{:?}", c.try_borrow().is_err());
7 | }
编译:成功
运行(退出码 0):
try_borrow_mut() 在已有可变借用时:true
try_borrow() 在已有可变借用时:true 源码:
1 | fn main() {
2 | let mut x = 5;
3 | let r = &x;
4 | let w = &mut x;
5 | println!("{} {}", r, w);
6 | }
编译:失败
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
--> <实验目录>/src/u32d.rs:4:13
|
3 | let r = &x;
| -- immutable borrow occurs here
4 | let w = &mut x;
| ^^^^^^ mutable borrow occurs here
5 | println!("{} {}", r, w);
| - immutable borrow later used here
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0502`.编译期借用规则见不可变借用与可变借用。
源码:
1 | use std::cell::RefCell;
2 | use std::rc::Rc;
3 | fn main() {
4 | let shared = Rc::new(RefCell::new(Vec::<i32>::new()));
5 | let a = Rc::clone(&shared); let b = Rc::clone(&shared);
6 | a.borrow_mut().push(1);
7 | b.borrow_mut().push(2);
8 | println!("两个所有者各自 push 一次,共享的 Vec = {:?}", shared.borrow());
9 | }
编译:成功
运行(退出码 0):
两个所有者各自 push 一次,共享的 Vec = [1, 2]
编译:成功
运行(退出码 0):
size_of::<u64>() = 8,size_of::<RefCell<u64>>() = 16(借用标志是一个 isize,占 8 字节)
size_of::<u8>() = 1,size_of::<RefCell<u8>>() = 16