为什么 `Cell<T>` 上没有实现 `Deref`?

6
Cell只是一种内联存储/包装类型,用于控制内部类型T的可变性/访问语义,并提供内部可变性功能。根据Rust文档,Cell类型并没有实现Deref。为什么呢?Cell的实例始终处于有效状态(内存始终有效且已初始化)。这意味着在Cell上实现Deref时,它不可能引发恐慌,而这是实现Deref的要求之一。
为Cell提供Deref实现本来会很方便。
1个回答

17

但这样做是不可靠的!

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的存在)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接