【问题标题】:Why does calling a method on a mutable reference involve "borrowing"?为什么在可变引用上调用方法涉及“借用”?
【发布时间】:2015-03-03 13:41:12
【问题描述】:

我正在学习 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

我不明白...我只是在可变引用上调用一个方法,为什么该行会涉及借用?

【问题讨论】:

    标签: rust


    【解决方案1】:

    我只是在可变引用上调用一个方法,为什么该行会涉及借用?

    当您在一个对象上调用一个将改变该对象的方法时,您不能有对该对象的任何其他引用未完成。如果您这样做了,您的突变可能会使这些引用无效并使您的程序处于不一致的状态。例如,假设您从哈希图中获取了一个值,然后添加了一个新值。添加新值会达到魔法限制并强制重新分配内存,您的值现在指向无处!当您使用该值时...该程序爆炸了!

    在这种情况下,您似乎想要执行相对常见的“如果缺少则追加或插入”操作。为此,您需要使用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)
    }
    

    【讨论】:

      【解决方案2】:

      因为你调用了一个可变借用的方法

      昨天我有一个关于 Hash 的类似问题,直到我注意到文档中的某些内容。 The docs for BTreeMap 显示以 fn insert(&amp;mut self.. 开头的 insert 的方法签名

      因此,当您调用 .insert 时,您是在隐含地要求该函数将 BTreeMap 借用为可变的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-02
        • 1970-01-01
        • 2019-05-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多