`在构建排序链表时,不能移出`& mut`-pointer`的解除引用

时间:2015-01-03 01:58:03

标签: data-structures rust

所以,我正在学习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日起每晚使用。

1 个答案:

答案 0 :(得分:3)

这是similar example

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不是Copyable。这意味着当你分配它时,你移动它从NodeItemself),因此不再完全定义它!这将是一件坏事,因此Rust阻止你这样做。

您必须决定解决问题的正确方法。最简单的方法是确保T可以复制(或者Cloneable,具体取决于您的数据)。但是,您可能不想想要复制您的数据。我会调查更改你的代码,以防止复制节点,只是更新条目。您可能需要使用类似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);
}