对同一个选项进行多次匹配会创建太多对self的可变引用



这是一个概念性问题,但此代码不编译:

struct HashHolder{
pub thing: HashMap<usize, usize>,
}
impl HashHolder {
fn insert(&mut self, item: &usize) {
let test = self.thing.get(item).clone(); // immutable borrow occurs here
for i in 0..10 {
match test { // immutable borrow later used here
Some(t) => {
//nothing
},
None => {
self.thing.insert(0, item.clone()); // mutable borrow occurs here
}
}
}
}
}

它给出了";error[E00502]:不能借用CCD_ 1作为可变的,因为它也被借用为不可变的";,并高亮显示上面所示的线条。

然而,如果我去掉for循环,它编译得很好!在我看来,无论哪种方式,这都应该毫无问题地编译:match的范围在循环的每个迭代中结束,所以所有引用都应该是";新鲜的";。如果我删除循环并只是第二次复制粘贴match块,也会产生同样的错误。

我对引用/借用的理解是:

  1. self是免疫借用的self.thing.get(item)。但在clone()之后,它应该释放这笔借款吗
  2. selfself.thing.insert(...);处被可变地借用,但是一旦self.thing0完成执行,该借用也应该被释放

所以我不明白为什么会发生这个错误。此外,编译器突出显示的行是无用的,因为没有for循环的这三行是完全可以的!

我对这段代码中发生的事情的理解有什么错吗?如果我想多次匹配,什么是更好的结构?

这种方法的部分原因是,在我的实际项目中,test的值会在循环中变化,并且在某些情况下可以给定一个值,因此match在不同的迭代中可能表现不同。也许这不是我想要的行为的最佳方法,但我仍然想理解为什么它甚至不会编译。

self.thing.get(item)返回一个类型为Option<&usize>的值,该值包含对self.thing的引用。当您克隆此值时,您只克隆Option,您会得到另一个Option<&usize>,它仍然包含对self.thing的引用。如果您想获得一个拥有的值,您需要使用Option::cloned(或Option::copied,因为usizeCopy)克隆内部值,这将给您一个Option<usize>

最新更新