为什么我无法移出 Rust 中的 HashMap?

问题描述 投票:0回答:1

在这个最小的可重现示例中,我们有一个哈希映射,其值包含

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

我理解说

Vec<T>
hashmap
将移至
second_vec
(“移出共享引用”部分)的部分。但是,我不明白的是:为什么这是一个错误,因为我不会再在范围内使用
hashmap
?根据我的理解,只有当我在代码中的其他地方引用移动的值时,此移动才会出现问题。

我听说它是强制用户使用

remove()
,它的作用与上面的代码相同,但是以更惯用的方式(因为我们不必取消引用该值,就像
hashmap.get() 发生的那样) 
)。

这是真的吗?这种行为的原因是什么?

rust borrow-checker
1个回答
0
投票

Rust 是一种强类型语言,这是一种设计决策,旨在防止人们做出导致未定义行为或安全代码中内存不安全的事情。

其中一部分是所有权:当您拥有

T
时,您拥有它并且可以随心所欲地使用它,但是当您拥有
&T
时,那么您只是借用它,其他人拥有它。

当您使用

get
方法时,您仅获得一个引用,因此,您无法移动底层
T
(在本例中为
Vec<i32>
)。如果它是
Copy
,而
Vec<i32>
不是,您可以轻松地将其复制到新的
T
中,但否则,即使引用的所有者即将离开,您也无法移出引用。如果您有
&mut T
,则可以移出引用,前提是您将其替换为其他内容,例如使用
std::mem::take
,但不可变引用是不可变的。

这样做的原因是,这会产生简单、易于推理的行为,并且实现起来简单且高效。它还允许人们编写代码,例如防止从集合中删除项目,这在某些情况下可能是理想的。

如果您想从旧

HashMap
获得该项目的所有权,那么您必须先将其删除。

© www.soinside.com 2019 - 2024. All rights reserved.