不能借用可变的变量,因为在构建自引用HashMap时也借用了不可变的变量 [英] cannot borrow variable as mutable because it is also borrowed as immutable while building a self-referential HashMap

查看:160
本文介绍了不能借用可变的变量,因为在构建自引用HashMap时也借用了不可变的变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建自引用HashMap:

I'm trying to build a self-referential HashMap:

use std::collections::HashMap;

struct Node<'a> {
    byte: u8,
    map: HashMap<i32, &'a Node<'a>>,
}

fn main() {
    let mut network = HashMap::<u32, Node>::new();

    network.insert(0, Node { byte: 0, map: HashMap::<i32, &Node>::new() });
    network.insert(1, Node { byte: 1, map: HashMap::<i32, &Node>::new() });

    let zeroeth_node = network.get(&0).unwrap();
    let mut first_node = network.get_mut(&1).unwrap();

    first_node.map.insert(-1, zeroeth_node);
}

我遇到了借用检查器错误,但我不明白其原因-是我更新错误的HashMap的方法,还是我的自引用用法?

I'm running into a borrow-checker error, but I don't understand its source -- is it my method of updating the HashMap that is wrong, or my self-referential usage of it?

错误:

<anon>:15:26: 15:33 error: cannot borrow `network` as mutable because it is also borrowed as immutable [E0502]
<anon>:15     let mut first_node = network.get_mut(&1).unwrap();
                                   ^~~~~~~
<anon>:14:24: 14:31 note: previous borrow of `network` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `network` until the borrow ends
<anon>:14     let zeroeth_node = network.get(&0).unwrap();
                                 ^~~~~~~
<anon>:18:2: 18:2 note: previous borrow ends here
<anon>:8 fn main() {
...
<anon>:18 }
          ^

推荐答案

答案

这些类型的结构在Rust中很难制造.您的样本中缺少的主要内容是使用 RefCell 允许共享引用. RefCell将Rust的借位检查从编译时移至运行时,从而使您可以在内存位置中传递.但是,不要在任何地方都开始使用RefCell,因为它仅适用于此类情况,如果您试图以可变方式借用某些东西而又已经以可变方式借用了某些内容,则RefCell会导致您的程序进入panic!.这仅适用于在network中创建的Node.您将无法创建仅存在于单个Node内部的Node.

Answer

These types of structures can be hard to make in Rust. The main thing missing from your sample is the use of RefCell which allows for shared references. RefCells move Rust's borrow checking from compile-time to run-time, and thus allows you to pass around the memory location. However, don't start using RefCell everywhere, as it is only suitable for situations like this, and RefCells will cause your program to panic! if you attempt to mutably borrow something while it is already mutably borrowed. This will only work with Nodes created in network; you won't be able to create Nodes that exist purely inside of a single Node.

use std::collections::HashMap;
use std::cell::RefCell;
#[derive(Debug)]
struct Node<'a> {
    byte: u8,
    map: HashMap<i32, &'a RefCell<Node<'a>>>,
}

fn main() {
    let mut network = HashMap::new();

    network.insert(0, RefCell::new(Node { byte: 0, map: HashMap::new() }));
    network.insert(1, RefCell::new(Node { byte: 1, map: HashMap::new() }));

    let zero_node = network.get(&0).unwrap();
    zero_node.borrow_mut().byte = 2;

    let first_node = network.get(&1).unwrap();
    first_node.borrow_mut().map.insert(-1, zero_node);

    println!("{:#?}", network);
}

这篇关于不能借用可变的变量,因为在构建自引用HashMap时也借用了不可变的变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆