问题描述
来自 std::cell
文档,我看到 Cell
是仅与实现 Copy
的类型兼容".这意味着我必须将 RefCell
用于非 Copy
类型.
From the std::cell
documentation, I see that Cell
is "only compatible with types that implement Copy
". This means I must use RefCell
for non-Copy
types.
当我确实有一个Copy
类型时,使用一种类型的单元格比另一种类型有好处吗?我假设答案是是",否则这两种类型都不存在!使用一种类型比另一种类型有什么好处和权衡?
When I do have a Copy
type, is there a benefit to using one type of cell over another? I assume the answer is "yes", because otherwise both types wouldn't exist! What are the benefits and tradeoffs of using one type over the other?
这是一个愚蠢的虚构示例,它使用 Cell
和 RefCell
来实现相同的目标:
Here's a silly, made-up example that uses both Cell
and RefCell
to accomplish the same goal:
use std::cell::{Cell,RefCell};
struct ThingWithCell {
counter: Cell<u8>,
}
impl ThingWithCell {
fn new() -> ThingWithCell {
ThingWithCell { counter: Cell::new(0) }
}
fn increment(&self) {
self.counter.set(self.counter.get() + 1);
}
fn count(&self) -> u8 { self.counter.get() }
}
struct ThingWithRefCell {
counter: RefCell<u8>,
}
impl ThingWithRefCell {
fn new() -> ThingWithRefCell {
ThingWithRefCell { counter: RefCell::new(0) }
}
fn increment(&self) {
let mut counter = self.counter.borrow_mut();
*counter = *counter + 1;
}
fn count(&self) -> u8 { *self.counter.borrow_mut() }
}
fn main() {
let cell = ThingWithCell::new();
cell.increment();
println!("{}", cell.count());
let cell = ThingWithRefCell::new();
cell.increment();
println!("{}", cell.count());
}
推荐答案
我认为考虑 Cell
和 RefCell
之间的其他语义差异很重要:
I think it is important to take into account the other semantic differences between Cell
and RefCell
:
Cell
为您提供值,RefCell
提供参考Cell
从不恐慌,RefCell
可以恐慌
Cell
provides you values,RefCell
with referencesCell
never panics,RefCell
can panic
让我们想象一下这些差异很重要的情况:
Let us imagine a situation where these differences matter:
let cell = Cell::new(foo);
{
let mut value = cell.get();
// do some heavy processing on value
cell.set(value);
}
在这种情况下,如果我们想象一些带有大量回调的复杂工作流,并且 cell
是全局状态的一部分,则 cell
的内容可能是被修改为重处理"的副作用,当 value
写回 cell
时,这些潜在的变化将丢失.
In this case, if we imagine some complex workflow with a lot of callback and that cell
is part of a global state, it is possible that the contents of cell
are modified as a side effect of the "heavy processing", and these potential changes will be lost when value
is written back in cell
.
另一方面,使用RefCell
的类似代码:
On the other hand, a similar code using RefCell
:
let cell = RefCell::new(foo);
{
let mut_ref = cell.borrow_mut().unwrap();
// do some heavy processing on mut_ref
}
在这种情况下,禁止任何修改 cell
作为重处理"的副作用,并且会导致恐慌.因此,您可以确定 cell
的值在不使用 mut_ref
In this case, any modification of cell
as a side-effect of the "heavy processing" is forbidden, and would result into a panic. You thus are certain that the value of cell
will not change without using mut_ref
我会根据它所持有的值的语义来决定使用哪个,而不是简单的 Copy
特性.如果两者都可以接受,那么 Cell
比另一个更轻、更安全,因此会更可取.
I would decide which to use depending of the semantics of the value it holds, rather than simply the Copy
trait. If both are acceptable, then Cell
is lighter and safer than the other, and thus would be preferable.
这篇关于当我可以使用 Cell 或 RefCell 时,我应该选择哪个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!