【问题标题】:Cannot move out of borrowed content / cannot move out of behind a shared reference无法移出借用内容/无法移出共享参考
【发布时间】:2015-03-25 08:59:32
【问题描述】:

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

即使在阅读其他帖子后我也不明白错误:

这种错误的根源是什么?

【问题讨论】:

  • 你看过questions like this吗? (顺便说一句,字符串提供了.bytes() 方法。)
  • 是的,我调查过了,但不明白 :( 而且我的字符串是 std::string::String,根据文档,没有 .bytes() 方法
  • 它叫.as_bytes()
  • 事实上,谢谢,它可以与as_bytes() 一起使用,无需克隆。但我还是不明白为什么?
  • Stringstr 获取bytes 方法。

标签: reference rust move-semantics borrow-checker


【解决方案1】:

我们来看看into_bytes的签名:

fn into_bytes(self) -> Vec<u8>

这需要self,而不是对自我的引用(&amp;self)。这意味着self 将被使用,并且在通话后将不可用。取而代之的是Vec&lt;u8&gt;。前缀into_ 是表示此类方法的常用方式。

我不知道你的iter() 方法返回什么,但我猜它是&amp;String 的迭代器,也就是说,它返回对String 的引用,但不给你它们的所有权.这意味着您不能调用使用该值的方法

如您所见,一种解决方案是使用clone。这会创建一个您确实拥有的重复对象,并且可以调用into_bytes on。正如其他评论者所提到的,您也可以使用as_bytes,它采用&amp;self,因此它将适用于借来的值。您应该使用哪一个取决于您使用指针的最终目标。

在更大的范围内,这一切都与所有权的概念有关。某些操作取决于拥有该项目,而其他操作可以通过借用对象(可能是可变的)而逃脱。引用 (&amp;foo) 不授予所有权,它只是借用。

为什么在函数的参数中使用self 而不是&amp;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() {}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-04
    • 2020-09-11
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多