来自std::cell文档 http://doc.rust-lang.org/std/cell/index.html, 我看到Cell
是“仅与实现的类型兼容Copy
“。这意味着我必须使用RefCell
对于非Copy
types.
When I do have a Copy
类型,使用一种类型的电池比使用另一种类型有好处吗?我认为答案是“是”,因为否则这两种类型都不会存在!使用一种类型相对于另一种类型的优点和缺点是什么?
这是一个愚蠢的、虚构的例子,同时使用了两者Cell
and RefCell
为了实现同样的目标:
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
and RefCell
:
-
Cell
为您提供价值,RefCell
有参考文献
-
Cell
从不惊慌,RefCell
会惊慌
让我们想象一下这些差异很重要的情况:
let cell = Cell::new(foo);
{
let mut value = cell.get();
// do some heavy processing on value
cell.set(value);
}
在这种情况下,如果我们想象一些带有大量回调的复杂工作流程cell
是全局状态的一部分,其内容可能是cell
被修改为“重处理”的副作用,并且这些潜在的更改将在以下情况下丢失:value
被写回cell
.
另一方面,使用类似的代码RefCell
:
let cell = RefCell::new(foo);
{
let mut_ref = cell.borrow_mut().unwrap();
// do some heavy processing on mut_ref
}
在这种情况下,任何修改cell
因为“重度处理”的副作用是被禁止的,并且会导致恐慌。因此,您可以确定cell
不使用就不会改变mut_ref
我会根据它所持有的值的语义来决定使用哪个,而不是简单地Copy
特征。如果两者都可以接受的话Cell
比另一种更轻、更安全,因此是优选的。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)