当我可以使用 Cell 或 RefCell 时,我应该选择哪一个?

2024-03-26

来自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(使用前将#替换为@)

当我可以使用 Cell 或 RefCell 时,我应该选择哪一个? 的相关文章

随机推荐