为什么Rust中的Cell只能用于复制而不能用于克隆类型?

dth*_*dth 14 traits rust

Rust标准库的文档声明Cell只能用于Copy类型,并且在所有其他情况下应该使用RefCell,但不能解释原因.

研究文件和两者的代码后CellRefCell,它似乎是唯一重要的一点是get功能Cell.如果值是一个Copy类型,则可以返回这样的副本.但为什么克隆不够好?

可以直接在以下位置实现该set功能RefCell:

fn set<T>(r: &RefCell<T>, v: T) {
    *r.borrow_mut() = v
}
Run Code Online (Sandbox Code Playgroud)

这只有在没有其他人持有对该值的引用时才有效.但如果可以克隆该值,可以这样做:

fn get<T: Clone>(r: &RefCell<T>) -> T {
    r.borrow().clone()
}
Run Code Online (Sandbox Code Playgroud)

使用类型Cell处理Clone类型可以避免运行时借用检查的开销.我在这里错过了什么吗?

小智 10

它不健全.DK的评论.是在正确的轨道上,但你甚至不需要恐慌造成破坏.一个有问题的情况是:

  1. 单元格(连同Option)允许创建循环,即自引用类型
  2. Clone实施得到一个&self参考
  3. 在存在循环的情况下,Clone实现可以因此访问正被克隆的单元
  4. 因此,被克隆的对象可以覆盖自己,而它本身就有一个普通的借用(即&self)
  5. 借用时的覆盖是不合理的,因为它允许任意类型的惩罚和其他不良.例如,假设有Result<T, E>字段,其最初Ok(T),取到的基准T内部并覆盖ResultErr(R).然后&T突然提到一个E值.

这个例子可以归功于Huon Wilson,请参阅user.rust-lang.org主题为什么Cell需要Copy而不是Clone?.他的文章介绍了限制的更多结构性原因,并包括一个完整的代码示例.

  • 似乎直觉应该是简单的.Rust不允许同时共享和变异.`Cell`通过不提供对实际值的引用(不共享)来解决这个问题,但`.clone()`会将引用作为参数. (2认同)