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 !!!

Playground link

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)

Rust相关问答推荐

程序退出后只写入指定管道的数据

PyReadonlyArray2到Vec T<>

如何仅使用http机箱发送http请求?

有没有办法模仿对象安全克隆?

限制未使用的泛型导致编译错误

告诉Rust编译器返回值不包含构造函数中提供的引用

为什么在 Allocator API 中 allocate() 使用 `[u8]` 而 deallocate 使用 `u8` ?

当我try 使用 SKI 演算中的S I I实现递归时,为什么 Rust 会失败?

使用占位符获取用户输入

Rust LinkedList 中的borrow 判断器错误的原因是什么?

为什么我可以使用 &mut (**ref) 创建两个实时 &mut 到同一个变量?

Rust: 目标成员属于哪个"目标家族"的列表是否存在?

trait 对象指针的生命周期

如何在 Rust 中显式声明 std::str::Matches<'a, P> ?

如何连接 Rust 中的相邻切片

为什么我可以同时传递可变和不可变引用?

判断 is_ok 后重用结果

将一片字节复制到一个大小不匹配的数组中

BigUint 二进制补码

如何重写这个通用参数?