iterとinto_iterの違いは何ですか? 質問する

iterとinto_iterの違いは何ですか? 質問する

私は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)ため、のシグネチャに惑わされないでください)。また、それらの反復子は、 内の要素への参照を生成します。selfVec

これです不変の参照を生成する:

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 より前のバージョンを使用しており、次の事実を使用して問題をさらに複雑にしています。

  1. 当時は はIntoIteratorに対して実装されておら[T; N]ず、&[T; N]とに対してのみ実装されていました&mut [T; N]
  2. メソッドが値に対して実装されていない場合は、代わりにその値への参照が自動的に検索されます。

into_iterこれは、すべての型 ( を除く[T; N]) が 3 つのバリエーション (値と参照) すべてに対してこれを実装しているため、 にとっては非常に驚くべきことです。

配列は現在 (1.53.0 以降)IntoIterator通常の方法で実装されているため、もう驚くことはありません。

おすすめ記事