如何获得对存储在RefCell中的 struct 的不同字段的可变引用.获得对 struct 的不同字段的可变引用有什么害处?

use std::cell::{RefCell, RefMut};

#[derive(Default)]
struct A {
    a: i32,
    b: u32,
}

fn main() {
    let mut a_ref_cell: RefCell<A> = Default::default();
    let mut a_obj = a_ref_cell.borrow_mut();
    let a_ref = &mut a_obj.a;
    let b_ref = &mut a_obj.b;
    
    *a_ref = 2;
    *b_ref = 78;
    
    println!("{}, {}", *a_ref, *b_ref);
    println!("Hello, world!");
}

误差率

error[E0499]: cannot borrow `a_obj` as mutable more than once at a time
  --> src/lib.rs:62:22
   |
61 |     let a_ref = &mut a_obj.a;
   |                      ----- first mutable borrow occurs here
62 |     let b_ref = &mut a_obj.b;
   |                      ^^^^^ second mutable borrow occurs here
63 |     
64 |     *a_ref = 2;
   |     ---------- first borrow later used here

推荐答案

编译器理解将单个borrow 拆分为其字段的borrow .然而,这在这里行不通有一个看不见的原因:

let mut a_obj = a_ref_cell.borrow_mut();
let a_ref = &mut a_obj.a;
let b_ref = &mut a_obj.b;

a_obj不是一个可变的引用,而是一个std::cell::RefMut保护对象,它在被删除时释放借入,并在此之前通过DerefMut实现提供对内容的访问.因为DerefMut::deref_mut()原则上是任意的Rust代码,所以它被严格地视为与任何fn(&mut self) -> &mut SomethingElse函数一样--在再次调用它之前,您必须删除借入.

对于这个问题,简单的本地解决方案适用于任何类型的可解除引用的事物,即在寻址其字段之前borrow 一次警卫的内容.(我添加了类型注释以进行解释;不需要它们.)

let mut a_obj: RefMut<'_, A> = a_ref_cell.borrow_mut();
let a_obj: &mut A = &mut *a_obj;

现在,您可以单独borrow a_obj个字段.该borrow 也可以在相同的let中完成(这是通过应用于borrow_mut()调用的结果的temporary lifetime extension来允许的):

let a_obj = &mut *a_ref_cell.borrow_mut();

Rust相关问答推荐

如何在不安全的代码中初始化枚举 struct

把Vector3变成Vector4的绝妙方法

如何创建引用构造函数拥有的变量的对象?

如何仅使用http机箱发送http请求?

两个相关特征的冲突实现错误

值为可变对象的不可变HashMap

带扫描的铁 rust 使用滤镜

如何使用 list 在Rust for Windows中编译?

在Rust中,在实现特征`Display`时,如何获取调用方指定的格式?

避免在Collect()上进行涡鱼类型的涂抹,以产生<;Vec<;_>;,_>;

是否可以在不切换到下一个位置的情况下获得迭代器值:

允许 rust 迹 struct 条目具有多种类型

如何从宏调用闭包?

带引脚和不带引脚的比较功能

如何在 Rust 中编写一个通用方法,它可以接受任何可以转换为另一个值的值?

将多维数组转换为切片

Rust:`sort_by` 多个条件,冗长的模式匹配

在 Rust 中,我如何处理请求 javascript 的页面?

如何在 Rust 中编写修改 struct 的函数

如果返回类型是通用的,我可以返回 &str 输入的一部分吗?