Rust Rc Refcell的变异字段取决于其其他内部字段

Rust Rc Refcell的变异字段取决于其其他内部字段,rust,borrow-checker,rc,refcell,Rust,Borrow Checker,Rc,Refcell,我需要在Rc RefCell中迭代结构的一个字段,并根据它的另一个字段修改它的一些参数。 例如,对于struct Foo: pub struct Foo { pub foo1: Vec<bool>, pub foo2: Vec<i32>, } 我可以通过在可变借用之前克隆foo1并在闭包中使用克隆来解决这个问题,但这会导致不必要的复制。事实上,我基本上需要一个对foo2的可变引用和一个对foo1的不可变引用(请注意,这是简化的代码,压缩迭代器在这里不起作

我需要在Rc RefCell中迭代结构的一个字段,并根据它的另一个字段修改它的一些参数。 例如,对于struct Foo:

pub struct Foo {
    pub foo1: Vec<bool>,
    pub foo2: Vec<i32>,
}

我可以通过在可变借用之前克隆foo1并在闭包中使用克隆来解决这个问题,但这会导致不必要的复制。事实上,我基本上需要一个对foo2的可变引用和一个对foo1的不可变引用(请注意,这是简化的代码,压缩迭代器在这里不起作用)。我知道代码不符合借用规则。。有没有一种方法可以在不克隆数据的情况下实现这一点?

问题是,您试图在每个循环迭代中重新加载
RefCell
,而它已经被借用以在
foo2
上获取迭代器。解决方法是在循环之前使用一个
foo\u单元格。借用mut()
,并分别借用到
foo1
foo2

注意,
foo\u cell.borrow\u mut()
上的取消引用是实现此功能所必需的

use std::rc::Rc;
use std::cell::RefCell;

pub struct Foo {
    pub foo1: Vec<bool>,
    pub foo2: Vec<i32>,
}
fn main() {
    let foo_cell = Rc::new(RefCell::new(Foo {
        foo1: vec![true, false],
        foo2: vec![1, 2]
        
    }));
    // The dereference is required to get &mut Foo out of the RefMut<Foo>
    let borrow = &mut *foo_cell.borrow_mut();
    let foo1 = &borrow.foo1;

    borrow.foo2.iter_mut().enumerate().for_each(|(idx, foo2)| {
        if foo1[idx] {
            *foo2 *= -1;
        }
    });
}
使用std::rc::rc;
使用std::cell::RefCell;
pub struct Foo{
酒吧1:Vec,
酒吧2:Vec,
}
fn main(){
让foo_cell=Rc::new(RefCell::new(foo{
foo1:vec![对,错],
foo2:vec![1,2]
}));
//将&mut Foo从RefMut中取出需要取消引用
让我们借用=&mut*foo_单元格。借用_mut();
设foo1=&borrow.foo1;
foreach(|(idx,foo2)|{
如果foo1[idx]{
*foo2*=-1;
}
});
}

这是否回答了您的问题?关键部分是显式的重新箭头
&mut*
borrow_mut()
的返回值不仅仅是一个引用,它是一个实现
Deref
DerefMut
RefMut
结构。每次访问结构中的字段时,都会调用
deref()
deref\u mut()
方法,这对借用检查器来说是不透明的,因此它必须将整个结构标记为借用。一旦您提取了对整个结构的单个可变引用,借用检查器就会看到您正在访问该结构的各个字段,因为不再涉及不透明的方法调用。消除变量赋值和内联两个借词都不起作用,所以我想借词检查器实际上需要一些额外的帮助来赋值
let foo1=&brook.foo1在闭包外部。事实上,可变借阅可以内联为
borrow.foo2.iter_mut()…
。感谢您的解释,这很有效。我有点希望Ref和RefMut像常规引用一样工作,但我想这不是因为闭包中捕获变量的方式,所以不能内联这两个借用。在闭包中引用
&borrow.foo1
会使闭包捕获
borrow
,而不仅仅是
borrow.foo1
。在将来的某个时候,有一种方法可以使这项工作成功。
use std::rc::Rc;
use std::cell::RefCell;

pub struct Foo {
    pub foo1: Vec<bool>,
    pub foo2: Vec<i32>,
}
fn main() {
    let foo_cell = Rc::new(RefCell::new(Foo {
        foo1: vec![true, false],
        foo2: vec![1, 2]
        
    }));
    // The dereference is required to get &mut Foo out of the RefMut<Foo>
    let borrow = &mut *foo_cell.borrow_mut();
    let foo1 = &borrow.foo1;

    borrow.foo2.iter_mut().enumerate().for_each(|(idx, foo2)| {
        if foo1[idx] {
            *foo2 *= -1;
        }
    });
}