1. ホーム
  2. reference

[解決済み] 借用コンテンツから移動できない/共有リファレンスの後ろから移動できない

2022-02-10 14:59:39

質問事項

エラーメッセージがよくわからない 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() {

などの他の投稿を読んでも、このエラーがよくわかりません。

このようなエラーの原因は何でしょうか?

解決方法は?

のシグネチャを見てみましょう。 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() {}