【问题标题】:Is there any way to borrow a RefCell immutably and mutably at the same time?有什么办法可以同时不可变和可变地借用 RefCell 吗?
【发布时间】:2019-06-07 20:51:43
【问题描述】:

我有一段代码需要对列表进行操作。此列表包含来自其他来源且需要处理并最终删除的项目。该列表还传递给多个函数,这些函数决定是添加还是删除项目。我创建了一个反映我的问题的示例代码:

use std::{cell::RefCell, rc::Rc};

pub fn foo() {
    let list: Rc<RefCell<Vec<Rc<RefCell<String>>>>> = Rc::new(RefCell::new(Vec::new()));

    list.borrow_mut()
        .push(Rc::new(RefCell::new(String::from("ABC"))));

    while list.borrow().len() > 0 {
        let list_ref = list.borrow();

        let first_item = list_ref[0].borrow_mut();
        //item processing, needed as mutable

        list.borrow_mut().remove(0);
    }
}

这会在运行时出现恐慌:

thread 'main' panicked at 'already borrowed: BorrowMutError', src/libcore/result.rs:997:5

我想我理解这个问题:我有两个不可变的借用,然后第三个是可变的。根据 Rust 文档,这是不允许的:许多不可变借用或单个可变借用。有什么办法可以解决这个问题?

【问题讨论】:

  • 我今天才完成了 rust 书,我可能正在谈论我的后端 buuuuut 为什么不通过可变借用来完成大部分工作呢? play.rust-lang.org/…

标签: rust rc borrow refcell


【解决方案1】:

我不知道您实际上想要实现什么,因为您没有提供minimal reproducible example,但我认为您只是在数据结构中混淆了listitem 的借用,并且一开始就把你弄糊涂了。

尽管如此,以下代码(您可以在 playground 中运行)执行您上面描述的操作。

use std::{cell::RefCell, rc::Rc};

pub fn foo() {
    let list = Rc::new(RefCell::new(Vec::new()));
    let mut list = list.borrow_mut();

    let item = Rc::new(RefCell::new(String::from("ABC")));

    list.push(item);
    println!("list: {:?}", list);

    while let Some(item) = list.pop() {
        println!("item: {:?}", item);
        item.borrow_mut().push_str("DEF");
        println!("item: {:?}", item);
    }

    println!("list: {:?}", list);
}

fn main() {
    foo();
}

我在这里使用了两个技巧。

  1. 我只借用了一次 list,并且该借用是可变的,它允许我从中添加和删除项目。

  2. 因为您的描述说无论如何您都想从list 中删除项目,所以我能够使用popremove 方法迭代Vec(取决于您的顺序)希望从list 获得物品。这意味着我不必为循环的范围借用 Vec(如果你要迭代它,你会这样做)。

还有其他方法可以根据某些谓词删除元素。例如:Removing elements from a Vec based on some condition

要真正回答您最初的问题:没有办法安全地同时拥有不可变和可变借用。这是 Rust 使其内存安全的核心原则之一。想一想,如果同时在后台数据实际上可以更改,那么不变性将是一种什么样的保证?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-02
    • 2018-04-15
    • 2021-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多