gpt4 book ai didi

rust - 有没有办法同时不可变地和可变地借用 RefCell?

转载 作者:行者123 更新时间:2023-11-29 08:28:50 27 4
gpt4 key购买 nike

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

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);
}
}

这会在运行时发生 panic :

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

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

最佳答案

我不知道您实际上想要实现什么,因为您未能提供 minimal reproducible example , 但我认为你只是混淆了 list 的借用和 item在您的数据结构中,这首先让您感到困惑。

尽管如此,以下代码(您可以在 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 中删除项目无论如何,我能够遍历 Vecpopremove方法(取决于您希望从 list 中获取项目的顺序)。这意味着我不必借用 Vec对于循环的范围(如果你要迭代它,你会这样做)。

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

实际回答您最初的问题:无法同时安全地进行不可变和可变借用。这是 Rust 的核心原则之一,它使内存安全。想一想,如果同时在幕后数据实际上可能发生变化,那么不变性将是一种什么样的保证?

关于rust - 有没有办法同时不可变地和可变地借用 RefCell?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56501086/

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