编程Rust开发者

Rust中的集合(例如Vec、HashMap)是如何工作的?它们的所有权有什么特点,什么时候需要克隆元素或集合?

用 Hintsage AI 助手通过面试

答案

在Rust中,标准集合(如Vec<T>、HashMap<K,V>、HashSet<T>等)实现了对内容的所有权原则。这意味着集合拥有它所包含的所有对象,并负责在删除时释放它们的内存。

例如,放入Vec<T>中的元素会被移动(move)到向量中,向量随后拥有它们:

let s = String::from("hi"); let mut v = Vec::new(); v.push(s); // s现在被移动,不可访问

如果集合包含可复制的值,则会进行复制;如果是可移动的,则所有权将被转移。当需要在两个地方保留原始值时,需要克隆元素或集合,例如:

let name = String::from("Olga"); let mut v = Vec::new(); v.push(name.clone()); println!("{}", name); // name仍然可访问,因为它被克隆了

具有误导性的问题

在使用可移动数据类型(例如String)作为键时,向HashMap插入元素时会发生什么?在将其传递给HashMap::insert()后,原始键是否仍然可用?

常常给出错误的回答:“原始键在插入后仍然可用”。

实际上,键和值的所有权被转移给了HashMap,插入后在未预先克隆的情况下不能使用它们:

let key = String::from("id"); let mut map = std::collections::HashMap::new(); map.insert(key, 42); // key不再可用

尝试访问key将导致编译错误。

由于对该主题细节不熟悉而导致的实际错误示例


故事 开发者试图在插入到Vec后使用移动的对象,收到错误“value used here after move”,未理解Vector现在拥有它。


故事 在使用HashMap时忘记克隆字符串键,导致在其他地方无法使用它们,从而需要大量重构代码。


故事 在一个项目中,尝试在函数外返回对向量内部元素的引用,忘记了在改变向量大小时引用将失效。这导致了悬挂引用和运行时崩溃(panic)。