RefCell<T>

17 Mar 2025 | 4 分钟阅读

内部可变性 模式用于在拥有不可变引用的情况下修改引用。 RefCell<T> 可用于实现内部可变性。

要记住的要点

  • RefCell<T> 代表其所持数据的单一所有权。
  • 如果使用 RefCell<T>,则在运行时强制执行不变性。
  • RefCell<T> 主要用于单线程场景,如果在多线程情况下使用,则会报错。
  • RefCell<T> 在运行时检查可变借用。 因此,我们可以说即使 RefCell<T> 的值是不可变的,我们也可以修改该值。

内部可变性

根据借用规则,如果我们有一个不可变值,那么我们不能可变地借用。

让我们看一个简单的例子

输出

rust RefCell

在上面的例子中,我们已经看到不可变值不能被可变地借用。 但是,RefCell 是实现内部可变性的一种方法。

使用 RefCell<T> 在运行时跟踪借用

RefCell<T> 包含两种在运行时跟踪借用的方法

  • borrow(): borrow() 方法返回 Ref<T> 类型的智能指针。
  • borrow_mut(): borrow_mut() 方法返回 RefMut<<T> 类型的智能指针。

注意:Ref<T> 和 RefMut<T> 两种类型都实现了 Deref 特征。 因此,它们可以被视为常规引用。

一些重要点

  • RefCell<T> 记录当前有多少个 Ref<T> 和 Refmut<T> 智能指针处于活动状态。
  • 每当调用 borrow() 方法时,RefCell<T> 就会增加活动不可变借用的数量。 当 Rc<T> 超出范围时,RefCell<T> 会将计数减一。
  • RefCell<T> 允许我们拥有许多不可变借用,但一次只能有一个可变借用,就像编译时借用规则一样。 如果我们违反此规则,则 RefCell<T> 将在运行时 panic。

borrow() 方法

borrow() 方法借用不可变值。 可以在同一时间获取多个不可变借用。

语法

让我们看一个多重不可变借用发生的简单示例

输出

rust RefCell

让我们看一个 panic 状态的简单示例

输出

rust RefCell

在上面的示例中,程序在运行时 panic,因为不可变借用和可变借用不能同时发生。

borrow_mut() 方法

borrow_mut() 方法借用可变值。 可变借用可以发生一次。

语法

让我们看一个简单的例子


rust RefCell

让我们看一个 panic 状态的简单示例

输出

rust RefCell

在上面的示例中,可变借用发生了两次。 因此,程序在运行时 panic 并抛出错误“already borrowed: BorrowMutError”。

通过组合 Rc<T> 和 RefCell<T> 实现可变数据的多重所有者

我们可以组合 Rc<T> 和 RefCell<T>,这样我们就可以拥有可变数据的多个所有者。 Rc<T> 允许你拥有一个数据的多个所有者,但它仅提供对数据的不可变访问。 RefCell<T> 允许你修改数据。 因此,我们可以说 Rc<T> 和 RefCell<T> 的组合提供了拥有具有可变数据的多个所有者的灵活性。

让我们看一个简单的例子

输出

rust RefCell

在上面的示例中,我们创建一个变量“val”,并将值“java”存储到变量“val”中。 然后,我们创建列表“a”,并且克隆“val”变量,这样变量“a”和“val”都拥有“java”值,而不是将所有权从“val”转移到“a”变量。 创建列表“a”后,我们创建列表“b”和“c”并克隆列表“a”。 创建列表后,我们使用 borrow_mut() 方法将“val”变量的值替换为“C# language”。


下一主题#