我想实现树数据结构。我有一个Node
结构,希望它能够保存对子Node
的引用。我试过了:
use std::collections::*;
#[derive(Debug)]
struct Node {
value: String,
children: HashMap<String, Node>,
}
impl Node {
fn new(value: String) -> Self {
Node {
value: value,
children: HashMap::new(),
}
}
fn add_child(&mut self, key: String, value: String) -> &mut Node {
let mut node = Node::new(value);
self.children.insert(key, node);
&mut node
}
}
fn main() {
let mut root_node = Node::new("root".to_string());
root_node.add_child("child_1_1".to_string(), "child_1_1_value".to_string());
}
此代码无法编译:
error: `node` does not live long enough
--> src/main.rs:22:10
|
22 | &mut node
| ^^^^ does not live long enough
23 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the anonymous lifetime #1 defined on the body at 19:67...
--> src/main.rs:19:68
|
19 | fn add_child(&mut self, key: String, value: String) -> &mut Node {
| ____________________________________________________________________^ starting here...
20 | | let mut node = Node::new(value);
21 | | self.children.insert(key, node);
22 | | &mut node
23 | | }
| |___^ ...ending here
error[E0382]: use of moved value: `node`
--> src/main.rs:22:10
|
21 | self.children.insert(key, node);
| ---- value moved here
22 | &mut node
| ^^^^ value used here after move
|
= note: move occurs because `node` has type `Node`, which does not implement the `Copy` trait
我该如何实现?
答案 0 :(得分:2)
在这种情况下,实际需要查看编译器输出中的 second 错误消息:
error[E0382]: use of moved value: `node`
--> src/main.rs:22:10
|
21 | self.children.insert(key, node);
| ---- value moved here
22 | &mut node
| ^^^^ value used here after move
|
= note: move occurs because `node` has type `Node`, which does not implement the `Copy` trait
变量node
将移动到第21行的hashmap中。之后您无法使用它!在Rust中,我们有移动语义,这意味着默认情况下一切都被移动而不是默认克隆(C ++)或默认情况下被引用(Java)。您想要返回对1>}对象里面的哈希映射的引用!
一种简单的方法是插入Node
,就像你正在做的那样,然后从hashmap中获取值:
node
这应该清楚这个功能实际上做了什么。但是,这段代码有一些缺点:首先,我们必须克隆let mut node = Node::new(value);
self.children.insert(key.clone(), node);
self.children.get_mut(key).unwrap()
(我们需要它用于插入和查询);其次,hashmap需要计算密钥的哈希两次,这不是非常有效。
幸运的是,Rust key
有一个很好的entry()
-API。我们可以改变这样的功能:
HashMap
这是self.children.entry(key).or_insert_with(|| Node::new(value))
的整个身体!然而,现在我们注意到......如果hashmap已经包含与给定键相关联的值,我们还没有真正考虑过应该发生什么!在上面的代码中,保留并返回旧值。如果您想要执行其他操作(例如替换值),则可以在add_child()
对象上使用match
:
Entry