私はRustの例チュートリアルには次のコード スニペットがあります。
// Vec example
let vec1 = vec![1, 2, 3];
let vec2 = vec![4, 5, 6];
// `iter()` for vecs yields `&i32`. Destructure to `i32`.
println!("2 in vec1: {}", vec1.iter() .any(|&x| x == 2));
// `into_iter()` for vecs yields `i32`. No destructuring required.
println!("2 in vec2: {}", vec2.into_iter().any(| x| x == 2));
// Array example
let array1 = [1, 2, 3];
let array2 = [4, 5, 6];
// `iter()` for arrays yields `&i32`.
println!("2 in array1: {}", array1.iter() .any(|&x| x == 2));
// `into_iter()` for arrays unusually yields `&i32`.
println!("2 in array2: {}", array2.into_iter().any(|&x| x == 2));
私はかなり混乱しています。Vec
、イテレータは.iter
参照とイテレータを返します.into_iter
値が得られますが、配列これらの反復子は同一ですか?
これら 2 つの方法の使用例/API は何ですか?
ベストアンサー1
要約:
- によって返される反復子は、コンテキストに応じて、、または
into_iter
のいずれかを生成する場合があります。T
&T
&mut T
- によって返される反復子は、慣例により を
iter
生成します。&T
- によって返される反復子は、慣例により を
iter_mut
生成します。&mut T
最初の質問は、「 とは何ですかinto_iter
?」です。
into_iter
から来ているIntoIterator
特性:
pub trait IntoIterator where <Self::IntoIter as Iterator>::Item == Self::Item, { type Item; type IntoIter: Iterator; fn into_iter(self) -> Self::IntoIter; }
特定の型をイテレータに変換する方法を指定する場合に、この特性を実装します。特に注目すべきは、型がIntoIterator
それを実装している場合、ループ内で使用できることですfor
。
たとえば、Vec
実装はIntoIterator
... 3 回です。
impl<T> IntoIterator for Vec<T> impl<'a, T> IntoIterator for &'a Vec<T> impl<'a, T> IntoIterator for &'a mut Vec<T>
それぞれのバリエーションは若干異なります。
これは、Vec
とその反復子を消費します値を生み出す(T
直接):
impl<T> IntoIterator for Vec<T> { type Item = T; type IntoIter = IntoIter<T>; fn into_iter(mut self) -> IntoIter<T> { /* ... */ } }
他の 2 つは、ベクトルを参照によって受け取ります (はどちらの場合も参照であるinto_iter(self)
ため、のシグネチャに惑わされないでください)。また、それらの反復子は、 内の要素への参照を生成します。self
Vec
これです不変の参照を生成する:
impl<'a, T> IntoIterator for &'a Vec<T> { type Item = &'a T; type IntoIter = slice::Iter<'a, T>; fn into_iter(self) -> slice::Iter<'a, T> { /* ... */ } }
この可変参照を生成する:
impl<'a, T> IntoIterator for &'a mut Vec<T> { type Item = &'a mut T; type IntoIter = slice::IterMut<'a, T>; fn into_iter(self) -> slice::IterMut<'a, T> { /* ... */ } }
それで:
iter
との違いは何ですかinto_iter
?
into_iter
はイテレータを取得するための汎用メソッドですが、このイテレータが値、不変参照、または可変参照を生成するかどうかはコンテキストに依存し、予期しない結果になることがあります。
iter
およびiter_mut
はアドホック メソッドです。したがって、戻り値の型はコンテキストに依存せず、慣例的にそれぞれ不変参照と可変参照を生成するイテレータになります。
Rust by Example の投稿の著者は、into_iter
呼び出されるコンテキスト (つまり、型) への依存から生じる驚きを説明するために、Rust 1.53.0 より前のバージョンを使用しており、次の事実を使用して問題をさらに複雑にしています。
- 当時は は
IntoIterator
に対して実装されておら[T; N]
ず、&[T; N]
とに対してのみ実装されていました&mut [T; N]
。 - メソッドが値に対して実装されていない場合は、代わりにその値への参照が自動的に検索されます。
into_iter
これは、すべての型 ( を除く[T; N]
) が 3 つのバリエーション (値と参照) すべてに対してこれを実装しているため、 にとっては非常に驚くべきことです。
配列は現在 (1.53.0 以降)IntoIterator
通常の方法で実装されているため、もう驚くことはありません。