我想创建一个简单的链表并在其中添加一个值.如何add实现该方法以100 50 10 5在第42行进行此代码输出,第二次root.print()调用?
use std::rc::Rc;
struct Node {
value: i32,
next: Option<Box<Node>>,
}
impl Node {
fn print(&self) {
let mut current = self;
loop {
println!("{}", current.value);
match current.next {
Some(ref next) => {
current = &**next;
}
None => break,
}
}
}
fn add(&mut self, node: Node) {
let item = Some(Box::new(node));
let mut current = self;
loop {
match current.next {
None => current.next = item,
_ => {}
//Some(next) => { current = next; }
}
}
}
}
fn main() {
let leaf = Node {
value: 10,
next: None,
};
let branch = Node {
value: 50,
next: Some(Box::new(leaf)),
};
let mut root = Node {
value: 100,
next: Some(Box::new(branch)),
};
root.print();
let new_leaf = Node {
value: 5,
next: None,
};
root.add(new_leaf);
root.print();
}
Run Code Online (Sandbox Code Playgroud)
我重写了这个函数:
fn add(&mut self, node: Node) {
let item = Some(Box::new(node));
let mut current = self;
loop {
match current {
&mut Node {
value: _,
next: None,
} => current.next = item,
_ => {}
//Some(next) => { current = next; }
}
}
}
Run Code Online (Sandbox Code Playgroud)
但编译说
error[E0382]: use of moved value: `item`
--> <anon>:28:40
|
28 | None => current.next = item,
| ^^^^ value moved here in previous iteration of loop
|
= note: move occurs because `item` has type `std::option::Option<std::boxed::Box<Node>>`, which does not implement the `Copy` trait
Run Code Online (Sandbox Code Playgroud)
我不明白为什么它说如果项目只使用过一次之前已被移动,以及如何实现Some(_)分支以遍历列表?
这就是你需要写它的方式(游乐场链接)
fn add(&mut self, node: Node) {
let item = Some(Box::new(node));
let mut current = self;
loop {
match moving(current).next {
ref mut slot @ None => {
*slot = item;
return;
}
Some(ref mut next) => current = next,
};
}
}
Run Code Online (Sandbox Code Playgroud)
好的,这是什么?
第1步,我们需要return在使用后立即使用该值item.然后编译器正确地看到它只从一次移动.
ref mut slot @ None => {
*slot = item;
return;
}
Run Code Online (Sandbox Code Playgroud)
第2步,循环使用&mut我们沿途更新的指针是棘手的.
默认情况下,生锈reborrow一个&mut被取消引用.只要借用的产品仍然存在,它就不会消耗参考,它只是考虑借用它.
显然,这在这里效果不佳.我们希望从旧current到新的"交接" current.我们可以强制&mut指针服从移动语义.
我们需要这个(identity函数强制移动!):
match moving(current).next
Run Code Online (Sandbox Code Playgroud)
我们也可以这样写:
let tmp = current;
match tmp.next
Run Code Online (Sandbox Code Playgroud)
或这个:
match {current}.next
Run Code Online (Sandbox Code Playgroud)
第3步,我们在里面查找后没有当前指针,所以要调整代码.
ref mut slot保持下一个值的位置.