本文介绍了当我可以使用 Cell 或 RefCell 时,我应该选择哪个?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自 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?

这是一个愚蠢的虚构示例,它使用 CellRefCell 来实现相同的目标:

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());
}

推荐答案

我认为考虑 CellRefCell 之间的其他语义差异很重要:

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 references
  • Cell 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 时,我应该选择哪个?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-02 00:10