Rust standard library的文档说明,Cell只能用于Copy种类型,在所有其他情况下,应该使用RefCell,但没有确切解释原因.

在研究了CellRefCell的文档和代码之后,唯一重要的一点似乎是Cellget函数.如果值是Copy类型,则可以返回这样的副本.但为什么克隆人还不够好呢?

可以直接在RefCell上实现set功能:

fn set<T>(r: &RefCell<T>, v: T) {
    *r.borrow_mut() = v
}

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

fn get<T: Clone>(r: &RefCell<T>) -> T {
    r.borrow().clone()
}

使用像Cell这样的类型处理Clone个类型可以避免运行时借阅判断的开销.我有什么遗漏吗?

推荐答案

这是不合理的.由DK comments .是在正确的轨道上,但你甚至不需要惊慌来造成混乱.一个有问题的情况是:

  1. 单元格(连同Option个)允许创建循环,即自引用类型
  2. Clone实现获得&self引用
  3. 在存在一个周期的情况下,Clone实现可能因此访问正在被克隆的细胞
  4. 因此,被克隆的对象可以覆盖自身,而它自身有一个普通的borrow (即&self)
  5. borrow 时覆盖是不合理的,因为它允许任意类型的双关语和其他不良行为.例如,假设有Result<T, E>个字段,最初是Ok(T),引用其中的T,然后用Err(R)覆盖Result.然后&T突然指的是E.

这个例子归功于Huon Wilson,请参见用户.rust-lang.org线程Why does Cell require Copy instead of Clone?.他的文章探讨了限制的更多 struct 性原因,还包括一个完整的代码示例.

Rust相关问答推荐

给定使用newype习语定义的类型上的铁 rust Vec,有没有方法获得底层原始类型的一部分?

如何为rust trait边界指定多种可能性

铁 rust 中的泛型:不能将`<;T作为添加>;::Output`除以`{Float}`

Tokio_Postgres行上未显示退回特性的生存期,且生命周期 不够长

为昂贵的for循环制作筛子

当对VEC;U8>;使用serde_json时,Base64编码是保护空间的好方法吗?

是否可以在不切换到下一个位置的情况下获得迭代器值:

如何实现Serde::Ser::Error的调试

rust 蚀生命周期 不匹配-不一定超过此处定义的生命周期

将Vec<;U8&>转换为Vec<;{Float}&>

Rust移动/复制涉及实际复制时进行检测

是否可以使用Serde/Rust全局处理无效的JSON值?

如何在 Rust 中将函数项变成函数指针

如何从 rust 中的同一父目录导入文件

我如何取消转义,在 Rust 中多次转义的字符串?

如何使用泛型满足 tokio 异步任务中的生命周期界限

Rust Serde 为 Option:: 创建反序列化器

如何获得对数组子集的工作可变引用?

从函数返回 u32 的数组/切片

当值是新类型包装器时,对键的奇怪 HashMap 生命周期要求