LoginSignup
7
3

More than 5 years have passed since last update.

rustでvectorから値を取り出そうとすると、cannot move out of indexed content

Posted at

Vectorから値を取り出そうとしてみる

main.rs
fn main() {
    #[derive(Debug)] 
    struct Num {
        num: u8
    }

    let zero = Num{num: 0};
    let one = Num{num: 1};
    let two = Num{num: 2};

    let vector = vec![zero, one, two];
    let zero = vector[0];
    println!("{:?}", zero);
}

これはコンパイルに通りません。
error[E0507]: cannot move out of indexed content

indexing

vectorの0番目の要素を取り出そうとして、vector[0]と書きました。
そもそもこの書き方はVectorが提供しているものではないのです。
[]を使った方法はVectorIndexトレイトを実装しているために使えるものです。
std::ops::Index - Rust
Vectorの値を取り出すメソッドにはgetが定義されています。

getとindexingの違い

getを使って次のように書き換えるとコンパイルに通ります。

main.rs
fn main() {
    #[derive(Debug)] 
    struct Num {
        num: u8
    }

    let zero = Num{num: 0};
    let one = Num{num: 1};
    let two = Num{num: 2};

    let vector = vec![zero, one, two];
    let zero = vector.get(0);
    println!("{:?}", zero);
}

Some(Num { num: 0 })

この違いはなんでしょうか。

indexの挙動

indexの挙動は次のようになります。

  • 要素がCopyを実装していればcopyした値を返す
  • Copyが実装されていない場合は、値を返す

NumCopyを実装していないため、indexで要素を取得しようとすると値がそのまま返されます。
すると、vectorの1つめの要素のNumの所有権が、vectorからzeroに移ることになります。
しかし、Vectorの要素の一部分だけ所有権がmoveすることは許されていいないため、コンパイルに通らないようです。

getの挙動

getは指定された場所にある要素の参照を返します。
そのため、zeroは要素の参照になるため、とくに問題はないのです。

copyを実装している場合

indexを利用しても、要素がCopyを実装していれば、copyされた値が返されるので所有権の問題は生じません。
以下はコンパイルに通ります。

fn main() {
    println!("{:?}", zero);

    let vector = vec![0, 1, 2];
    let zero = vector[0];
    println!("{}", zero);
}

参考

rust - What does "cannot move out of indexed content" mean? - Stack Overflow
std::vec::Vec - Rust
std::ops::Index - Rust

7
3
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3