这个问题被标记为重复,让人感到沮丧this question,因为这是 Rust 新手的另一个死胡同的例子。对于新手来说,从这些具体的答案中归纳总结起来非常困难,这意味着他们很快就会被下一个例子困住(参考:我自己)。
为了提供一点归纳总结,帮助解决“无法移动”的问题,需要考虑为什么问题首先会出现。这里有两个主要原因:
- 你不想声明拥有某个东西。
- 你想声明拥有某个东西。
在第一种情况下,您无意中做了一些需要拥有权的事情。解决方案是找到一种不需要所有权的替代品。这正是本问题和答案所概述的情况。与其使用消耗其输入并要求拥有所有权的into_bytes()
而应该使用as_bytes()
,它将完成相同的工作而不需要声明所有权。
解决方案不明显的原因是编译器假定您确实想使用line
,并帮助您将其替换为*line
。因此,它会抛出误导性错误,告诉您取消引用没有帮助。您会困惑于如何修复无法move
的问题,从而导致像clone()
这样的临时解决方法。
实际上,您从一开始就不想取消引用,只需要找到适用于借用引用的替代方法即可。
现在,在第二种情况(这是我在顶部提到的“重复”问答中更相关的情况)中,错误是相同的,但您无意中借用而不是声明所有权。当实现方法时,通常会使用对self
的引用,而不是消耗它。顺便说一下,这是完全可选的 - 方法可以选择消耗而不是借用self
,尽管我无法想象除非该方法返回一个Self
,否则这很实用。
在第二种情况下,令人困惑的是,绝望的clone()
似乎又一次解决了问题,至少在短期内是这样。但考虑到根本原因,根本修复方法略有不同。既然您确实想要声明所有权(也许您正在尝试删除数据或将其转移给另一个所有者),那么您需要明确表示。
在简单的情况下,这可能只涉及从变量来源中删除&
- 无论是您调用的函数的返回值还是当前函数的参数。
通常情况下,你无法进行改变。相反,你必须剥夺所有权。但是你不能让当前所有者手空无一物 - 你需要留给他们一些有效的东西。我所知道的唯一方法是使用
std::mem
中的
take
、
swap
或
replace
之一。在1.40中发布的
take
是最简单的方法 - 它只是给所有者提供了
Default
值,并将当前值的所有权交给了你。如果类型没有
Default
,则
swap
和
replace
提供了以前所有者的其他内容,这尤其重要。
这里有一个示例:
pub struct SimpleLinkedList<T> {
head: Option<Box<Node<T>>>
}
pub struct Node<T> {
value: T,
next: Option<Box<Node<T>>>
}
impl<T> SimpleLinkedList<T> {
pub fn pop(&mut self) -> Option<T> {
if self.head.is_none() { return None; }
let value = self.head.unwrap().value;
self.head = self.head.unwrap().next;
return Some(value);
}
}
这会抛出“无法移动位于可变引用后面的self.head
”错误,因为unwrap()
会消耗self
。
有很多方法可以改进这个问题,但是为了说明目的,只需要这些就足够了:
use std::mem;
pub struct SimpleLinkedList<T> {
head: Option<Box<Node<T>>>
}
pub struct Node<T> {
value: T,
next: Option<Box<Node<T>>>
}
impl<T> SimpleLinkedList<T> {
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() { return None; }
let old_head = mem::take(&mut self.head);
let old_head_unwrapped = old_head.unwrap();
self.head = old_head_unwrapped.next;
return Some(old_head_unwrapped.value);
}
}
我们无论如何都要替换self.head
的值,因此通过在其上调用take
,我们可以声明所有权。然后我们可以自由地将其传递给unwrap()
并随后覆盖原始的self.head
。
所以总之,为什么会出现“无法移动借用的内容/引用”的情况?要么是因为你只需要借用,并且必须确保你所做的任何事情都不会消耗它,要么是因为你实际上想要消耗并且必须拥有所有权。
.as_bytes()
。 - blussas_bytes()
而不进行克隆就可以工作。但我仍然不明白为什么? - PeekmoString
从str
中获取bytes
方法。 - huon