Cell只是一种内联存储/包装类型,它控制内部类型T的可变性/访问语义,并提供内部可变性功能.从rust documentation开始,Deref
不适用于Cell<T>
类型.为什么会这样呢?Cell<T>
的实例始终处于有效状态(内存始终有效且已初始化).这意味着当在Cell<T>
上实现Deref
时,它不可能死机,这是实现Deref
的要求之一.
提供Deref
个Iml换取Cell<T>
个Iml会很方便.
Cell只是一种内联存储/包装类型,它控制内部类型T的可变性/访问语义,并提供内部可变性功能.从rust documentation开始,Deref
不适用于Cell<T>
类型.为什么会这样呢?Cell<T>
的实例始终处于有效状态(内存始终有效且已初始化).这意味着当在Cell<T>
上实现Deref
时,它不可能死机,这是实现Deref
的要求之一.
提供Deref
个Iml换取Cell<T>
个Iml会很方便.
但这是不合理的!
Cell<T>
的前提是它never提供对其内容的引用(实际上,这就是它的sibling RefCell<T>
所做的),因此对它的所有读写操作都是原子的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: not in the "threadsafe" sense
2: it can do this soundly by using an UnsafeCell
: a compiler builtin that says "trust me compiler, I can enforce borrowing rules, so you don't have to"
3: outside of an UnsafeCell
(&T
doesn't know about the Cell
)