借用したコンテンツから移動できない、または共有参照の背後から移動できない


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

はい、調べましたが理解できませんでした:(そして、私の文字列はstd :: string :: Stringです。ドキュメントによると、.bytes()メソッドはありません
Peekmo

4
それは呼ばれています.as_bytes()
ブラス

実際、ありがとうございますas_bytes()。クローンなしで動作します。しかし、それでも理由がわかりませんか?
Peekmo、2015年

Stringbytesからメソッドを取得しstrます。
huon

回答:


108

の署名を見てみましょうinto_bytes

fn into_bytes(self) -> Vec<u8>

これはself、self(&self)への参照ではなくを受け取ります。つまり、selfされ、消費とコールした後に使用できなくなります。その代わりに、Vec<u8>。プレフィックスinto_は、このようなメソッドを示す一般的な方法です。

私はあなたのiter()メソッドが何を返すのか正確にはわかりませんが、それはのイテレータであることを推測します&String。つまり、それはaへの参照を返しますが、Stringそれらの所有権を与えません。つまり、値を消費するメソッドを呼び出すことはできません

ご存じのように、1つの解決策はを使用することcloneです。これにより、あなた所有し、呼び出すことができる複製オブジェクトが作成さinto_bytesれます。他のコメンターが言及しているように、あなたはas_byteswhich takeを使用することもできる&selfので、借りた値で動作します。どちらを使用するかは、ポインターで何をするかという最終目標によって異なります。

大きな画像では、これはすべて所有権の概念に関係しています。特定の操作はアイテムの所有に依存し、他の操作はオブジェクトを借用することで回避できます(おそらく変更可能)。参照(&foo)は所有権を付与するのではなく、単なる借用です。

関数の引数のself代わりに使用することが興味深いのはなぜ&selfですか?

所有権の譲渡は、一般的に有用な概念です。私が何かを終えたとき、誰かがそれを持っているかもしれません。Rustでは、これはより効率的な方法です。コピーを割り当て、1つのコピーを与えてから、私のコピーを捨てることを回避できます。所有権も最も寛容な状態です。オブジェクトを所有している場合、私はそれを好きなように使用できます。


テスト用に作成したコードは次のとおりです。

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() {}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.