所以,我正在学习Rust并决定构建一个已排序的链表。在我到达add方法之前,一切看起来都很好,这里是代码:
struct NodeItem<'a, V:'a + Ord> {
value : V,
next : Box<Option<NodeItem<'a,V>>> // '
}
impl <'a, V:'a + Ord> NodeItem<'a,V> { // '
fn new(value : V) -> NodeItem<'a,V> { // '
NodeItem { value : value, next : box None }
}
fn add(&mut self, value : V) {
match self.value.cmp(&value) {
Less => {
self.next = box Some(NodeItem {value: self.value, next : self.next });
self.value = value;
},
Equal | Greater => {
match *self.next {
Some(ref mut next) => next.add(value),
None => self.next = box Some(NodeItem::new(value)),
}
},
}
}
}
编译器抱怨:
/home/mauricio/projects/rust/data_structures/src/lists/mod.rs:16:47: 16:51 error: cannot move out of dereference of `&mut`-pointer
/home/mauricio/projects/rust/data_structures/src/lists/mod.rs:16 self.next = box Some(NodeItem {value: self.value, next : self.next });
^~~~
/home/mauricio/projects/rust/data_structures/src/lists/mod.rs:16:66: 16:70 error: cannot move out of dereference of `&mut`-pointer
/home/mauricio/projects/rust/data_structures/src/lists/mod.rs:16 self.next = box Some(NodeItem {value: self.value, next : self.next });
这里究竟出现了什么问题?我知道我正在移动其他地方的引用,但是生命参数不应该表明这些项目有相关的“生命”吗?
这是从2014年12月21日起每晚使用。
答案 0 :(得分:3)
enum E { Hello }
struct A(E);
fn main() {
let mut a = A(E::Hello);
let b = &mut a;
let c = b.0;
}
错误:
<anon>:7:13: 7:14 error: cannot move out of dereference of `&mut`-pointer
<anon>:7 let c = b.0;
^
<anon>:7:9: 7:10 note: attempting to move value to here
<anon>:7 let c = b.0;
^
<anon>:7:9: 7:10 help: to prevent the move, use `ref c` or `ref mut c` to capture value by reference
<anon>:7 let c = b.0;
^
请注意,编译器会告诉您如何在这种情况下防止错误。
问题是您的self.value
不是Copy
able。这意味着当你分配它时,你移动它从NodeItem
(self
),因此不再完全定义它!这将是一件坏事,因此Rust阻止你这样做。
您必须决定解决问题的正确方法。最简单的方法是确保T
可以复制(或者Clone
able,具体取决于您的数据)。但是,您可能不想想要复制您的数据。我会调查更改你的代码,以防止复制节点,只是更新条目。您可能需要使用类似swap
的内容。
#[derive(Debug)]
struct Node<T> {
v: T,
next: Option<Box<Node<T>>>,
}
impl<T> Node<T> {
fn new(v: T) -> Node<T> { Node { v: v, next: None } }
fn push_front(self, head: T) -> Node<T> {
Node {
v: head,
next: Some(Box::new(self)),
}
}
fn push_back(&mut self, tail: T) {
match self.next {
Some(ref mut next) => next.push_back(tail),
None => self.next = Some(Box::new(Node::new(tail))),
}
}
fn push_after(&mut self, v: T) {
let old_next = self.next.take();
let new_next = Node {
v: v,
next: old_next,
};
self.next = Some(Box::new(new_next));
}
}
fn main() {
let mut n = Node::new(2u8);
n.push_back(3u8);
let mut n = n.push_front(0u8);
n.push_after(1u8);
println!("{:?}", n);
}