Cell/RefCell

在rust所有权系统中:

在同一时间,一个数据只能有一个可变引用(&mut T),或者多个不可变引用(&T),但不能同时存在两者。

fn main() {
    let mut a = 1;
    let b = &mut a;
    let c = &a;
    println!("{a}_{b}_{c}");
    // ^^^^^^^^^^^^^^^^^^^ 报错 因为同时存在可变引用和不可变引用
}

Cell<T>

Cell<T> 没有借用检查规则,可以在拥有不可变引用的同时修改目标数据。

use std::cell::{Cell};

fn main() {
  let a = Cell::new("hello");
  let b = a.get(); // 读
  a.set("world"); // 写
  let c = a.get(); // 读
  println!("{:?} {b} {c}", a);
}

但:Cell<T>要求使用者必须实现了Copy trait。

RefCell<T>

RefCell 实际上并没有解决可变引用和引用可以共存的问题, 只是将报错从编译期推迟到运行时,从编译器错误变成了 panic 异常。

use std::cell::{RefCell};

fn main() {
  let a = RefCell::new("hello");
  let b = a.borrow();
  let c = a.borrow_mut();
  println!("{:?} {b}, {c}", a);
  // 编译期间不报错,但运行时报错
}