2016-11-15 8 views
2

構造体のスライスをループするとき、値は参考になりますが、多くの場合、var(*var)と書かなければならない場合があります。Rustのリファレンスではなく、スライスの値を反復処理しますか?

変数を再宣言しないようにするより良い方法はありますか?

fn my_fn(slice: &[MyStruct]) { 
    for var in slice { 
     let var = *var; // <-- how to avoid this? 

     // Without the line above, errors in comments occur: 

     other_fn(var); // <-- expected struct `MyStruct`, found reference 

     if var != var.other { 
      // ^^ trait `&MyStruct: std::cmp::PartialEq<MyStruct>>` not satisfied 
      foo(); 
     } 
    } 
} 

参照してください:actual error output(もっと不可解)。

+0

あなたはポインタなしであなたが望むことができるでしょう。 –

+0

いいえ、この場合はありません。一部の操作は機能しますが、十分な操作はありません。 – ideasman42

+0

'var'をそのまま使うのではなく、' let var = * var'を使う必要がある場合の例を挙げることができますか? –

答えて

14

あなたはthe patternに構造化代入によって参照を削除することができます

// | 
// v 
for &var in slice { 
    other_fn(var); 
} 

をしかし、これが唯一のCopy -typesためを作品! Copyではなく、Clone - オンリータイプの場合、になります。cloned()イテレーターアダプターを使用します。詳細については、Chris Emersonの答えをご覧ください。 Cloneでないタイプの場合は、それを行う機会はありません。

+0

これは正解です。 –

9

イテラブルを使用できる場合は、値を直接反復することができます。 Vec::into_iter()を使用してください。スライスを使用すると、clonedを使用することができます。

fn main() { 
    let v = vec![1, 2, 3]; 
    let slice = &v[..]; 
    for u in slice.iter().cloned() { 
     let u: usize = u; // prove it's really usize, not &usize 
     println!("{}", u); 
    } 
} 

をこれは明らかにクローン可能なされている項目に依存しています。結局のところ参照をしたいと思うかもしれません。

+0

これはLukasの答えほど効率的ではありません。さらに、 'slice'は変更可能ではないので、イテレータが消費される可能性がありますが、' slice'自体はそうではないので、複製は必要ありません。 –

+2

@EliSadoff実際、私たちのソリューションのどちらも、おそらく同じ最適化されたアセンブリ出力をもたらすでしょう。完全なスライスまたは反復子は複製されませんが、生成される各要素は複製されません。 –

+0

@LukasKalbertodtあなたは正しいです。私はまた、これが説明する 'クローン'対 'コピー'物について考えなかった。 –