Cell 1 2 3 4 5 6 7 8 9 use std::cell::Cell; fn main() { let data : Cell<i32> = Cell::new(100); let p = &data; data.set(10); println! ("{}", p.get()); p.set(20); println! ("{:? }", data); }
这次编译通过,执行,结果是符合我们的预期的:
10
Cell { value: 20 }
这里虽然变量都没用mut去声明,但是通过set函数改变了内部值。所谓的内部可变性。
cell 的api
1 2 3 4 5 6 7 8 9 10 impl<T> Cell<T> { pub fn get_mut(&mut self) -> &mut T { } pub fn set(&self, val: T) { } pub fn swap(&self, other: &Self) { } pub fn replace(&self, val: T) -> T { } pub fn into_inner(self) -> T { } } impl<T:Copy> Cell<T> { pub fn get(&self) -> T { } }
RefCell Cell类型没办法制造出直接指向内部数据的指针,而RefCell可以。
1 2 3 4 5 6 7 8 impl<T: ? Sized> RefCell<T> { pub fn borrow(&self) -> Ref<T> { } pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError> { } pub fn borrow_mut(&self) -> RefMut<T> { } pub fn try_borrow_mut(&self) -> Result<RefMut<T>, BorrowMutError> { } pub fn get_mut(&mut self) -> &mut T { } }
use std::cell::RefCell;
fn main() {
let shared_vec: RefCell<Vec<isize>> = RefCell::new(vec! [1, 2, 3]);
let shared1 = &shared_vec;
let shared2 = &shared1;
shared1.borrow_mut().push(4);
println! ("{:? }", shared_vec.borrow());
shared2.borrow_mut().push(5);
println! ("{:? }", shared_vec.borrow());
}
1 2 3 4 5 6 $ ./test [1, 2, 3, 4] [1, 2, 3, 4, 5]
一个panic实例
1 2 3 4 5 6 7 8 9 10 use std::cell::RefCell; fn main() { let shared_vec: RefCell<Vec<isize>> = RefCell::new(vec! [1, 2, 3]); let shared1 = &shared_vec; let shared2 = &shared1; let p1 = shared1.borrow(); let p2 = &p1[0]; shared2.borrow_mut().push(4); println! ("{}", p2); }
输出
1 2 3 4 $ ./test thread 'main' panicked at 'already borrowed: BorrowMutError', src\libcore\ result.rs:860:4 note: Run with `RUST_BACKTRACE=1` for a backtrace.
RefCell内部有一个“借用计数器”,调用borrow方法的时候,计数器里面的“共享引用计数”值就加1。当这个borrow结束的时候,会将这个值自动减1。同样,borrow_mut方法被调用的时候,它就记录一下当前存在“可变引用”。如果“共享引用”和“可变引用”同时出现了,就会报错。