1. ホーム

[解決済み】iterとinto_iterの違いは何ですか?

2022-04-28 10:01:44

質問

をやっています。 例によって錆び チュートリアルに、このようなコードがあります。

// 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は何ですか?

どのように解決するのですか?

TL;DR。

  • が返すイテレータは into_iter のいずれかを得ることができます。 T , &T または &mut T 文脈によって異なります。
  • が返すイテレータは iter&T 慣例により
  • が返すイテレータは iter_mut&mut T 慣例により

最初の質問は、"何ですか? into_iter ?quot。

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;
}

特定の型をどのようにイテレータに変換するかを指定したい場合に、この trait を実装します。最も顕著なのは、もしある型が 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> { /* ... */ }
}

他の二つは、参照によってベクトルを取ります。 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> { /* ... */ }
}


だから

とはどのような違いがあるのでしょうか? iterinto_iter ?

into_iter は、イテレータが値、不変参照、可変参照を生成するかどうかを取得する汎用的なメソッドです。 はコンテキストに依存します。 と驚くことがあります。

iteriter_mut はアドホックなメソッドです。したがって、それらの戻り値の型はコンテキストに依存せず、慣例的にそれぞれ不変参照と可変参照を返すイテレータとなります。

Rust by Exampleの著者は、このようなコンテキスト(つまり型)への依存から生じる驚きを、Rust by Exampleの投稿で説明しています。 into_iter が呼び出されるという事実を利用して、さらに問題を複雑にしている。

  1. IntoIterator は実装されていません。 [T; N] のみであり &[T; N]&mut [T; N] -- 2021年のラスト向けとなります。
  2. ある値に対してメソッドが実装されていない場合、自動的に検索されるのは リファレンス の代わりに、その値に対する

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

配列の実装 IntoIterator (への参照を反復できるようにするためです。 for のループになります。

Rust 1.51 では、配列に値を返すイテレータを実装することが可能です (via. array::IntoIter を実装していますが、既存の IntoIterator を自動的に参照する による値ごとの繰り返しを実装することは困難です。 IntoIterator .