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