Reference 尝试转移所有权时无法移出借用的内容

Reference 尝试转移所有权时无法移出借用的内容,reference,rust,move-semantics,borrow-checker,Reference,Rust,Move Semantics,Borrow Checker,我正在写一个链表,让我的头脑围绕着生锈的生命周期、所有权和参考资料。我有以下代码: pub struct LinkedList { head: Option<Box<LinkedListNode>>, } pub struct LinkedListNode { next: Option<Box<LinkedListNode>>, } impl LinkedList { pub fn new() -> LinkedL

我正在写一个链表,让我的头脑围绕着生锈的生命周期、所有权和参考资料。我有以下代码:

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() {}
较新版本的Rust有一个稍微不同的错误:

error[E0507]:无法移出共享引用后面的“*head”
-->src/main.rs:18:52
|
18 |一些(参考头部)=>新的_节点。下一步=一些(*头部),
|^^^^发生移动是因为“*head”的类型为“std::boxed::Box”,而该类型未实现“Copy”特性
我认为
head
节点当前必须属于
self
,这是一个链表。当我将其分配给
新节点时。下一步
,可能会发生所有权变更

如果可能的话,我宁愿不克隆该值,因为这似乎是浪费。我不想在函数期间“借用”它。我真的想转让它的所有权

我该怎么做

我已经看过了

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

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

尝试转移所有权时无法移出借用的内容

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

您根本无法将
移出
&self
,因为您无法更改该值

不能将
移出
&mut self
,因为这会使
链接列表
结构处于不一致的状态-其中一个字段的值未定义。这是Rust安全保证的核心措施

通常,您需要遵循中的某个内容来替换现有值

在这种情况下,您可以使用。这将使变量保持在原来的位置,将其更改为
None
,并返回以前的值。然后,您可以使用该值构建列表的新标题:

pub fn prepend_value(&mut self) {
    let head = self.head.take();
    self.head = Some(Box::new(LinkedListNode { next: head }));
}
一个更通用的解决方案是获得结构的所有权,而不是借用它。这允许你做任何你想做的事情。请注意,我们根据值而不是参考值获取
self

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

您认为这两种解决方案中哪一种更为惯用的代码?由于您有一个
节点
和一个包装器
列表
,我可能会使用带有
take
的版本;我认为人们比自己更了解自己。如果列表只是由
节点组成,则必须使用
self
版本。我可能会将其注释为
#[必须使用]
,以帮助指导用户。