为什么在这种情况下我需要强制借用范围?没有它,k.keep("X")
将导致编译错误。
mod keep {
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::HashMap;
use std::hash::Hash;
pub struct Keeper<T> {
index: Vec<T>,
kept: HashMap<T, usize>
}
impl<T> Keeper<T> {
pub fn new() -> Keeper<T> where T: Eq + Hash {
Keeper { index: Vec::new(), kept: HashMap::new() }
}
pub fn keep(&mut self, keepsake: T) -> usize where T: Eq + Hash + Copy {
match self.kept.entry(keepsake) {
Occupied(_) => (),
Vacant(entry) => {
entry.insert(self.index.len());
self.index.push(keepsake);
}
}
*self.kept.get(&keepsake).unwrap()
}
pub fn find(&self, i:usize) -> &T {
&self.index[i]
}
}
}
fn main() {
let mut k: keep::Keeper<&str> = keep::Keeper::new();
{ // forced borrow scoping
let (k1, k2, k3) = (k.keep("A"), k.keep("A"), k.keep("B"));
println!("{}@[{:p}], {}@[{:p}], {}@[{:p}]", k1, &k1, k2, &k2, k3, &k3);
let (s1, s2, s3) = (k.find(k1), k.find(k2), k.find(k3));
println!("{}@[{:p}], {}@[{:p}], {}@[{:p}]", s1, s1, s2, s2, s3, s3);
}
let k4 = k.keep("X");
}
答案 0 :(得分:1)
这是一个非常简单的案例;在以下绑定中:
let (s1, s2, s3) = (k.find(k1), k.find(k2), k.find(k3));
你不可避免地借用k
3次(你可以有多次不可变借用),所以只要s1
,s2
和s3
在范围内,你就可以不要随意借用k
。
通过引入自己的范围,您s1
,s2
和s3
会在其阻止结束时释放借款。
答案 1 :(得分:1)
最小复制:
struct Foo {
something: i32,
}
impl Foo {
fn give_something(&self) -> &i32 {
&self.something
}
fn bar(&mut self) {}
}
fn main() {
let mut foo = Foo{ something: 42, };
// In the following line, you borrow self.something with thing,
// therefore, foo is borrowed too:
let thing = foo.give_something();
// Then you cannot mutably borrow foo since it is already borrowed:
foo.bar();
}
所有都在编译器的解释中:
不能将
foo
借用为可变的,因为它也被借用为不可变的
你可以在一个东西上有一个可变的引用,或者有多个不可变的引用,而不是两个。
现在在您的代码中看到:您首先借用k
作为不可变的:
let (s1, s2, s3) = (k.find(k1), k.find(k2), k.find(k3));
然后你要求借用它是可变的:
let k4 = k.keep("X");