尝试转让所有权时,无法摆脱借来的内容

Gil*_*les 14 reference move-semantics rust borrow-checker

我正在编写一个链表来包围Rust的生命周期,所有权和引用.我有以下代码:

pub struct LinkedList {
    head: Option<Box<LinkedListNode>>,
}

pub struct LinkedListNode {
    next: Option<Box<LinkedListNode>>,
}

impl LinkedList {
    pub fn new() -> LinkedList {
        LinkedList { head: None }
    }

    pub fn prepend_value(&mut self) {
        let mut new_node = LinkedListNode { next: None };

        match self.head {
            Some(ref head) => new_node.next = Some(*head),
            None => new_node.next = None,
        };

        self.head = Some(Box::new(new_node));
    }
}

fn main() {}
Run Code Online (Sandbox Code Playgroud)

但是我收到以下编译错误:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:18:52
   |
18 |             Some(ref head) => new_node.next = Some(*head),
   |                                                    ^^^^^ cannot move out of borrowed content
Run Code Online (Sandbox Code Playgroud)

我认为head节点当前必须由self链接列表拥有.当我分配给它时new_node.next,可能会发生所有权变更.

如果可能的话,我宁愿不克隆价值,因为这看起来很浪费.我不想在函数期间"借用"它.我真的想转让它的所有权.

我怎么做?

我已经看过错误:无法移出借来的内容并且不能移出借来的内容.

我尝试按照其中一个问题中接受的答案中的建议删除匹配臂,并next在创建新的中进行定义LinkedListNode,但是我得到了相同的错误消息.

我已经成功添加了一个append方法,它将a LinkedListNode添加到列表的末尾.

She*_*ter 26

尝试转让所有权时,无法摆脱借来的内容

在高层次上,这对Rust来说是违规的.你不能转让借来的东西的所有权,因为你不拥有它.你不应该借我的车(&Car),然后把它交给你在街上看到的第一个人!即使我借给你我的车并允许你对它进行更改(&mut Car),这仍然是正确的.

你根本无法移动head,&self因为你无法改变价值.

您不能移出heada,&mut self因为这会使LinkedList结构处于不一致状态 - 其中一个字段将具有未定义的值.这是Rust安全保障的核心指标.

通常,您需要遵循以下内容:如何在可变引用中为字段交换新值?替换现有价值.

在这种情况下,您可以使用Option::take.这将使变量保持原样,将其原地更改为a None并返回先前的值.然后,您可以使用该值来构建列表的新头:

pub fn prepend_value(&mut self) {
    let head = self.head.take();
    self.head = Some(Box::new(LinkedListNode { next: head }));
}
Run Code Online (Sandbox Code Playgroud)

更通用的解决方案是获取结构的所有权而不是借用它.这允许你做任何你想做的事情.请注意,我们采用self按值,而不是按引用:

pub fn prepend_value(mut self) -> LinkedList {
    self.head = Some(Box::new(LinkedListNode { next: self.head }));
    self
} 
Run Code Online (Sandbox Code Playgroud)