不能从借来的内容中移出/不能从共享引用的后面移出

我不明白这个错误 cannot move out of borrowed content。我收到它很多次,我总是解决它,但我从来不明白为什么。

例如:

for line in self.xslg_file.iter() {
self.buffer.clear();


for current_char in line.into_bytes().iter() {
self.buffer.push(*current_char as char);
}


println!("{}", line);
}

产生错误:

error[E0507]: cannot move out of borrowed content
--> src/main.rs:31:33
|
31 |             for current_char in line.into_bytes().iter() {
|                                 ^^^^ cannot move out of borrowed content

在 Rust 的新版本中,错误是

error[E0507]: cannot move out of `*line` which is behind a shared reference
--> src/main.rs:31:33
|
31 |             for current_char in line.into_bytes().iter() {
|                                 ^^^^ move occurs because `*line` has type `std::string::String`, which does not implement the `Copy` trait

我通过克隆 line解决了这个问题:

for current_char in line.clone().into_bytes().iter() {

我不明白这个错误,即使我读了其他的文章,比如:

这种错误的根源是什么?

92823 次浏览

让我们看看 into_bytes的签名:

fn into_bytes(self) -> Vec<u8>

这需要 self,而不是对 self (&self)的引用。这意味着 self将是 消耗殆尽,并且在呼叫之后不可用。取而代之的是 Vec<u8>。前缀 into_是表示这样的方法的常用方法。

我不知道 iter()方法究竟返回什么,但我猜测它是 &String上的迭代器,也就是说,它返回对 String的引用,但不给出它们的所有权。也就是说你是 不能调用使用该值的方法

正如您所发现的,一种解决方案是使用 clone。这将创建一个您拥有的重复对象,并且可以对其调用 into_bytes。正如其他评论者提到的,您也可以使用 as_bytes,它接受 &self,因此它将在借来的值上工作。您应该使用哪一个取决于您的最终目标是如何处理指针。

从大局来看,这一切都与 所有权的概念有关。某些操作依赖于拥有该项,而其他操作可以借用该对象(也许是可变的)。参考资料(&foo)不授予所有权,它只是借用。

为什么在函数的参数中使用 self而不是 &self是有趣的呢?

一般来说,转让所有权是一个很有用的概念——当我完成某件事情时,其他人可能会拥有它。在 Rust 这是一种更有效率的方法。我可以避免分配一个副本,给你一个副本,然后扔掉我的副本。所有权也是最宽松的状态; 如果我拥有一个对象,我可以随心所欲地处理它。


下面是我创建用于测试的代码:

struct IteratorOfStringReference<'a>(&'a String);


impl<'a> Iterator for IteratorOfStringReference<'a> {
type Item = &'a String;


fn next(&mut self) -> Option<Self::Item> {
None
}
}


struct FileLikeThing {
string: String,
}


impl FileLikeThing {
fn iter(&self) -> IteratorOfStringReference {
IteratorOfStringReference(&self.string)
}
}


struct Dummy {
xslg_file: FileLikeThing,
buffer: String,
}


impl Dummy {
fn dummy(&mut self) {
for line in self.xslg_file.iter() {
self.buffer.clear();


for current_char in line.into_bytes().iter() {
self.buffer.push(*current_char as char);
}


println!("{}", line);
}
}
}


fn main() {}