Cell只是一种内联存储/包装类型,用于控制内部类型T的可变性/访问语义,并提供内部可变性功能。根据Rust文档,Cell类型并没有实现Deref。为什么呢?Cell的实例始终处于有效状态(内存始终有效且已初始化)。这意味着在Cell上实现Deref时,它不可能引发恐慌,而这是实现Deref的要求之一。
为Cell提供Deref实现本来会很方便。
为Cell提供Deref实现本来会很方便。
但这样做是不可靠的!
Cell
的前提是它从不提供对其内容的引用(事实上,这就是它的兄弟RefCell
的作用),因此对它的所有读写操作都是原子操作1。
作为其实现的一部分,Cell
具有以下签名的set
方法:
fn set(&self, val: T)
&Cell<T>
的值,也就是共享引用后面的单元格的值2。这就是内部可变性的工作原理。Cell
内容的引用:let cell = Cell::new(1);
let one: &i32 = &*cell;
set
方法:cell.set(2);
&T
)指向的数据,这是UB3!println!("one = {}", *one); // one = 2 !!!
1: 不是"线程安全"的意思
2: 它可以通过使用UnsafeCell
来安全地实现这一点:这是一个编译器内置的功能,它告诉编译器"相信我,我可以强制执行借用规则,所以你不必担心"
3: 在UnsafeCell
之外(&T
不知道Cell
的存在)