我正在学习Rust,我正试图将这段代码编译成编译:
use std::vec::Vec;
use std::collections::BTreeMap;
struct Occ {
docnum: u64,
weight: f32,
}
struct PostWriter<'a> {
bytes: Vec<u8>,
occurrences: BTreeMap<&'a [u8], Vec<Occ>>,
}
impl<'a> PostWriter<'a> {
fn new() -> PostWriter<'a> {
PostWriter {
bytes: Vec::new(),
occurrences: BTreeMap::new(),
}
}
fn add_occurrence(&'a mut self, term: &[u8], occ: Occ) {
let occurrences = &mut self.occurrences;
match occurrences.get_mut(term) {
Some(x) => x.push(occ),
None => {
// Add the term bytes to the big vector of all terms
let termstart = self.bytes.len();
self.bytes.extend(term);
// Create a new occurrences vector
let occs = vec![occ];
// Take the appended term as a slice to use as a key
// ERROR: cannot borrow `*occurrences` as mutable more than once at a time
occurrences.insert(&self.bytes[termstart..], occs);
}
}
}
}
fn main() {}
我收到错误:
error[E0499]: cannot borrow `*occurrences` as mutable more than once at a time
--> src/main.rs:34:17
|
24 | match occurrences.get_mut(term) {
| ----------- first mutable borrow occurs here
...
34 | occurrences.insert(&self.bytes[termstart..], occs);
| ^^^^^^^^^^^ second mutable borrow occurs here
35 | }
36 | }
| - first borrow ends here
我不明白......我只是在一个可变引用上调用一个方法,为什么这行涉及借用?
答案 0 :(得分:9)
我只是在一个可变引用上调用一个方法,为什么该行涉及借用?
当您在某个对象上调用某个方法来改变该对象时,您无法该对象的任何其他引用。如果您这样做,您的突变可能会使这些引用无效并使您的程序处于不一致状态。例如,假设您从hashmap中获取了一个值,然后添加了一个新值。添加新值会达到魔法限制并强制重新分配内存,您的值现在无处可寻!当你使用那个价值时... bang就是程序!
在这种情况下,看起来你想做相对常见的&#34;追加或插入,如果遗漏&#34;操作。您需要使用entry
:
use std::collections::BTreeMap;
fn main() {
let mut map = BTreeMap::new();
{
let nicknames = map.entry("joe").or_insert(Vec::new());
nicknames.push("shmoe");
// Using scoping to indicate that we are done with borrowing `nicknames`
// If we didn't, then we couldn't borrow map as
// immutable because we could still change it via `nicknames`
}
println!("{:?}", map)
}
答案 1 :(得分:1)
我昨天有一个关于Hash的类似问题,直到我注意到文档中的某些内容。 The docs for BTreeMap显示以insert
fn insert(&mut self..
的方法签名
所以当你调用.insert
时,你隐含地要求该函数将BTreeMap借用为可变的。