gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-29 07:40:42 24 4
gpt4 key购买 nike

来自std::cell documentation ,我看到 Cell 是“只与实现 Copy 的类型兼容”。这意味着我必须对非 Copy 类型使用 RefCell

当我确实有一个Copy类型时,使用一种类型的单元格比使用另一种类型的单元格有好处吗?我假设答案是"is",因为否则这两种类型都不会存在!使用一种类型相对于另一种类型的优势和权衡是什么?

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

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 之间的其他语义差异很重要:

  • Cell 为您提供值,RefCell 带有引用
  • Cell 从不 panic ,RefCell 会 panic

让我们想象一下这些差异很重要的情况:

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 的任何修改都是被禁止的,并且会导致 panic 。因此,您可以确定 cell 的值在不使用 mut_ref

的情况下不会改变

我会根据它所持有的值的语义来决定使用哪个,而不是简单地使用 Copy 特性。如果两者都可以接受,那么 Cell 比另一个更轻、更安全,因此会更可取。

关于rust - 当我可以使用 Cell 或 RefCell 时,我应该选择哪个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30275982/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com