这是一个概念性问题,但此代码不编译:
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
块,也会产生同样的错误。
我对引用/借用的理解是:
self
是免疫借用的self.thing.get(item)
。但在clone()
之后,它应该释放这笔借款吗self
在self.thing.insert(...);
处被可变地借用,但是一旦self.thing
0完成执行,该借用也应该被释放
所以我不明白为什么会发生这个错误。此外,编译器突出显示的行是无用的,因为没有for循环的这三行是完全可以的!
我对这段代码中发生的事情的理解有什么错吗?如果我想多次匹配,什么是更好的结构?
这种方法的部分原因是,在我的实际项目中,test
的值会在循环中变化,并且在某些情况下可以给定一个值,因此match
在不同的迭代中可能表现不同。也许这不是我想要的行为的最佳方法,但我仍然想理解为什么它甚至不会编译。
self.thing.get(item)
返回一个类型为Option<&usize>
的值,该值包含对self.thing
的引用。当您克隆此值时,您只克隆Option
,您会得到另一个Option<&usize>
,它仍然包含对self.thing
的引用。如果您想获得一个拥有的值,您需要使用Option::cloned
(或Option::copied
,因为usize
是Copy
)克隆内部值,这将给您一个Option<usize>
。