Rust:多次借用结构实例作为可变的实例失败,即使使用了范围 [duplicate]

Rust: borrow struct instance as mutable multiple times fails, even though scopes are used [duplicate]

提问人:zingi 提问时间:4/12/2020 更新时间:4/12/2020 访问量:226

问:

我正在尝试创建一个结构,其中包含一个哈希图和一个向量,因此向量应该包含对哈希图中值的引用

我认为当放入独立范围时,同一实例上的多个可变借用是可能的。

(操场)

use std::collections::HashMap;

struct Container<'a> {
    map: HashMap<String, String>,
    vec: Vec<&'a String>
}

impl<'a> Container<'a> {
    pub fn new() -> Self {
        Container {
            map: HashMap::new(),
            vec: Vec::new()
        }
    }

    pub fn add_link(&'a mut self, key: &str) {
        if let Some(value) = self.map.get(key) {
            self.vec.push(value);
        }
    }

    pub fn print_vec(&self) {
        println!("Vec: {:?}", self.vec);
    }
}

fn main() {
    let mut container = Container::new();

    {
        container.map.insert("a".to_string(), "x".to_string());
    }
    {
        container.map.insert("b".to_string(), "y".to_string());
    }
    {
        container.map.insert("c".to_string(), "z".to_string());
    }

    {
        container.add_link("c");
    }
    {
        container.add_link("a");
    }
    {
        container.add_link("c");
    }
    {
        container.add_link("k");
    }

    container.print_vec();
}
error[E0499]: cannot borrow `container` as mutable more than once at a time
  --> src/main.rs:44:9
   |
41 |         container.add_link("c");
   |         --------- first mutable borrow occurs here
...
44 |         container.add_link("a");
   |         ^^^^^^^^^
   |         |
   |         second mutable borrow occurs here
   |         first borrow later used here


(...)

我期望输出为:Vec: ["z", "x", "z"]

结构 可变 借用检查器 借贷

评论

0赞 zingi 4/12/2020
我正在阅读这个答案,但我不太明白我必须在我的代码中更改什么才能使其工作。
2赞 SCappella 4/12/2020
没有简单的答案。你要做的不是一个简单的问题(例如,如果必须重新分配会发生什么?如前所述,这将使向量中的所有引用无效,这不好)。仔细阅读链接问题的答案,然后做出决定。HashMap

答:

0赞 zingi 4/12/2020 #1

tl;博士

实现自引用结构(还不是 1.41.1)是一件容易的事。

就像@SCappella提到的,这里已经有一个更详细的方法来解决这个问题。


我解决这个问题的方法是绕过最初的问题,将我的容器结构拆分为两个单独的结构,其中引用结构与拥有数据的结构是分开的。

(操场)

use std::collections::HashMap;

struct Container {
    map: HashMap<String, String>,
}

struct DependentContainer<'a> {
    vec: Vec<&'a String>,
}

impl Container {
    pub fn new() -> Self {
        Container {
            map: HashMap::new(),
        }
    }

    pub fn add(&mut self, key: &str, value: &str) {
        self.map.insert(key.to_string(), value.to_string());
    }
}

impl<'a> DependentContainer<'a> {
    pub fn new() -> Self {
        DependentContainer {
            vec: Vec::new()
        }
    }

    pub fn add_link(&mut self, container: &'a Container, key: &str) {
        if let Some(value)= container.map.get(key) {
            self.vec.push(value);
        }
    }

    pub fn print_vec(&self) {
        println!("Vec: {:?}", self.vec);
    }
}

fn main() {
    let mut container = Container::new();
    let mut dep_container = DependentContainer::new();

    container.add("a", "x");
    container.add("b", "y");
    container.add("c", "z");

    dep_container.add_link(&container, "c");
    dep_container.add_link(&container, "a");
    dep_container.add_link(&container, "c");
    dep_container.add_link(&container, "k");

    dep_container.print_vec();
}