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
版本。我可能会将其注释为#[必须使用]
,以帮助指导用户。