为什么我不能在Rust中移出HashMap?

ubof19bj  于 2023-08-05  发布在  其他
关注(0)|答案(1)|浏览(113)

在这个最小可重复的例子中,我们有一个包含Vec<i32>的值的散列表,据我所知,Vec<T>并没有实现Copy,所以它会在需要的时候被移动。

use std::collections::HashMap;

#[derive(Clone)]
struct MyStruct {
    id: i32,
    vec_number: Vec<i32>,
}

fn main() {
    let mut hashmap: HashMap<i32, Vec<i32>> = HashMap::new();

    let a = MyStruct {
        id: 1,
        vec_number: vec![1, 2, 3],
    };

    let b = MyStruct {
        id: 2,
        vec_number: vec![1, 2, 3],
    };

    let first_vec = vec![a, b];
    
    for strct in first_vec {
        hashmap.insert(strct.id, strct.vec_number);
    }

    let second_vec : Vec<i32> = *hashmap.get(&2).unwrap(); // error here
}

字符串
我得到的错误是:

cannot move out of a shared reference
move occurs because value has type `Vec<i32>`, which does not implement the `Copy` trait


我理解说hashmap中的Vec<T>将被移动到second_vec的部分(“移出共享引用”部分)。然而,我不明白的是:为什么这是一个错误,因为我将不再在scope中使用hashmap?在我的理解中,只有当我在代码中的其他地方引用移动的值时,这种移动才会有问题。
我听说它是为了强制用户使用remove(),它的作用与上面的代码相同,但更习惯(因为我们不必像hashmap.get()那样导出值)。
这是真的吗?这种行为的原因是什么?

igsr9ssn

igsr9ssn1#

Rust是一种强类型语言,这是一个设计决策,以防止人们在安全代码中做导致未定义行为或内存不安全的事情。
其中一部分是所有权:当你有一个T时,你拥有它,可以随心所欲地使用它,但是当你有一个&T时,你只是借用它,别人拥有它。
当使用get方法时,您只获得一个引用,因此,您不能移动底层的T(在本例中为Vec<i32>)。如果它是Copy,而不是Vec<i32>,你可以简单地将它复制到一个新的T中,但否则,即使引用的所有者即将离开,你也不能移出引用。如果你有一个&mut T,你可以移出引用,只要你用其他东西来替换它,比如使用std::mem::take,但是不可变的引用是不可变的。
这样做的原因是,这产生了简单的、易于推理的行为,并且实现起来简单而有效。它还允许人们编写代码,例如,防止从集合中删除项,这在某些情况下可能是可取的。
如果您想从旧的HashMap中获取该项目的所有权,则必须首先删除它。

相关问题