无法移出借用的内容/不能移出共享引用的后面


127

我不明白这个错误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() {

即使阅读其他文章,我也无法理解错误:

这种错误的根源是什么?


1
你看过这样的问题吗?(顺便说一句,字符串提供了该.bytes()方法。)
huon 2015年

是的,我调查了一下,但听不懂:(而且我的字符串是std :: string :: String,根据文档,没有.bytes()方法
Peekmo

4
这叫做.as_bytes()
bluss

实际上,谢谢您,它as_bytes()无需克隆即可使用。但是我还是不明白为什么?
Peekmo

Stringbytes从获取方法str
huon 2015年

Answers:


108

让我们来看看的签名into_bytes

fn into_bytes(self) -> Vec<u8>

这需要self,而不是对self(&self)的引用。这意味着self它将被消耗,并且在通话后将不可用。取而代之的是Vec<u8>。前缀into_是表示此类方法的常用方式。

我不确切知道您的iter()方法返回什么,但是我猜想它是over的迭代器&String,也就是说,它返回对a的引用,String但不赋予您所有权。这意味着您不能调用使用该值的方法

如您所见,一种解决方案是使用clone。这将创建一个重复的对象,你自己,并且可以调用into_bytes上。就像其他评论者提到的那样,您还可以使用as_byteswhich &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() {}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.