提问人:Erhan Bagdemir 提问时间:10/30/2023 最后编辑:Erhan Bagdemir 更新时间:10/30/2023 访问量:81
无法移出“当前”,因为它是在从递归返回时借用的
Cannot move out of `current` because it is borrowed while returning from recursion
问:
让我们考虑一下我的存储结构,它包含 u16 中的键向量:
pub struct Storage {
...
pub root: Option<RefCell<Node>>,
}
pub struct Node {
pub keys: RefCell<Vec<u16>>,
pub children: RefCell<Vec<Node>>,
}
在递归期间的某个时间点,作为调用遍历子项的子项并搜索提供的键,
pub fn search(&'a self, key: u16, current: Ref<'a, Node>) -> (usize, Ref<'a, Node>) {
let keys = current.keys.borrow();
for index in 0..keys.len() {
if keys[index] == key && current.is_leaf() {
return (index, current);
}
}
}
递归通过 return 语句终止。函数调用应返回匹配键和当前 Node 实例的索引,以便调用方可以进行一些修改。但是,rustc 正在抱怨它:
error[E0505]: cannot move out of `current` because it is borrowed
--> src/index/btree.rs:87:36
|
84 | let keys = current.keys.borrow();
| ------- borrow of `current` occurs here
...
87 | return (index, current);
| ^^^^^^^ move out of `current` occurs here
...
90 | }
| - borrow might be used here, when `keys` is dropped and runs the destructor for type `Ref<'_, Vec<u16>>`
我知道该函数借用了第 84 行的键,只要“键”引用在附近,即直到它们在方法调用后被丢弃,但我的问题是在算法中处理这个问题的惯用方法是什么?尤其是在没有克隆对象的情况下,这对我来说听起来像是一种解决方法?
答:
1赞
Michael Anderson
10/30/2023
#1
我想你一定从你的例子中遗漏了一些重要的东西。它不会按原样编译。
更改它以解决最明显的问题,并从传递切换到仅传递,然后它为我编译:Ref<'a, Node>
&Node
use std::cell::RefCell;
pub struct Node {
pub keys: RefCell<Vec<u16>>,
pub children: RefCell<Vec<Node>>,
}
impl Node {
fn is_leaf(&self) -> bool {
todo!()
}
}
pub fn search(key: u16, current: &Node) -> Option<(usize, &Node)> {
let keys = current.keys.borrow();
for index in 0..keys.len() {
if keys[index] == key && current.is_leaf() {
return Some((index, current));
}
}
None
}
评论
0赞
Erhan Bagdemir
10/30/2023
谢谢迈克尔。该方法之所以将 Refs 作为参数,是因为 Node 的所有者 Storage(即 Storage)的内部可变性。我更新了上面的代码片段。因此,搜索从根节点开始,该节点是 RefCell。你对更好的惯用设计有什么建议吗?
0赞
Chayim Friedman
10/31/2023
@ErhanBagdemir 一般来说,没有什么理由采取.您始终可以通过(重新借用)它来转换它。Ref
Ref
&
&*
0赞
Michael Anderson
10/31/2023
@ErhanBagdemir创建一个最小的独立示例来演示该问题?(stackoverflow.com/help/minimal-reproducible-example)目前,代码中有太多其他错误,无法确定您要执行的操作。
评论