我正在编写一个链表来包围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() {}
但是我收到以下编译错误:
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
我认为head
节点当前必须由self
拥有,这是链接列表。当我将其分配给new_node.next
时,可能会发生所有权变更。
如果可能的话,我宁愿不克隆该值,因为这看起来很浪费。我不想只是“借”&#34;它在功能的持续时间内。我真的想转让它的所有权。
我该怎么做?
我已查看error: cannot move out of borrowed content on &mut self和Cannot move out of borrowed content。
我尝试按照其中一个问题的接受答案中的建议移除匹配部分,并在创建新next
时定义LinkedListNode
,但我收到相同的错误消息。
我已成功添加append
方法,该方法将LinkedListNode
添加到列表末尾。
答案 0 :(得分:24)
尝试转让所有权时无法摆脱借来的内容
在高级别,这对Rust来说是违规的。您无法转移借用的所有权,因为您不拥有。你不应该借我的车(&Car
),然后把它交给你在街上看到的第一个人!即使我借给你车并允许你对它进行更改(&mut Car
),这仍然是正确的。
您无法将head
移出&self
,因为您无法改变该值。
您无法将head
移出&mut self
,因为这会使LinkedList
结构处于不一致状态 - 其中一个字段将具有未定义的值。这是Rust安全保障的核心指标。
通常,您需要关注How can I swap in a new value for a field in a mutable reference to a structure?中的内容来替换现有值。
在这种情况下,您可以使用Option::take
。这将使变量保持原样,将其原地更改为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
}