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

wwtsj6pe  于 2022-12-23  发布在  其他
关注(0)|答案(1)|浏览(238)

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() {

我不明白的错误,即使在阅读其他职位,如:

这种错误的根源是什么?

eyh26e7m

eyh26e7m1#

让我们看看into_bytes的签名:

fn into_bytes(self) -> Vec<u8>

这需要self,而不是对self(&self)的引用。这意味着self将被“消耗”,并且在调用后不可用。在它的位置上,你得到一个Vec<u8>。前缀into_是表示此类方法的常用方式。
我不知道你的iter()方法到底返回了什么,但我猜它是&String上的迭代器,也就是说,它返回对String的引用,但不给予你它们的所有权,这意味着你 * 不能调用一个消耗值的方法 *。
正如你所发现的,一个解决方案是使用clone。这会创建一个你确实拥有的复制对象,并且可以调用into_bytes。正如其他评论者提到的,你也可以使用as_bytes,它接受&self,所以它将工作在一个借用的值上。你应该使用哪一个取决于你使用指针的最终目标。
从更大的Angular 来看,这一切都与 ownership 的概念有关。某些操作依赖于拥有项目,而其他操作可以通过借用对象(可能是可变的)来摆脱。引用(&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() {}

相关问题