イテレータについて整理
for式を書くと所有権まわりのエラーが出てしまい、よくわからなかったので整理する。
into_iter()
let numbers = vec![1, 2, 3];
for number in numbers {
// numberは要素そのもの
}
// numbersは再利用不可
公式ドキュメントにある通り、for式はコレクションに対してIntoIterator
トレイトのinto_iter()
を呼びIterator
トレイトを実装するものを生成する。そして、それに対しnext()
を呼ぶことで要素を取り出す。
fn into_iter(self) -> Self::IntoIter
定義によるとinto_iter()
はself
を受けるため、Copy
トレイトが実装されていなければmoveが発生する。なので、for式のあとで再利用しようとしてエラーが発生してしまう。
iter(), iter_mut()
let numbers = vec![1, 2, 3];
for number = numbers.iter() {
// numberは要素への参照
}
// numbersは再利用可
ここからの話はVec
型を想定する。moveを発生させたくない場合、iter()
やiter_mut()
を使う。
pub fn iter(&self) -> Iter<T>
into_iter()
とは違い、&self
を受けるのでmoveは発生しない。Vec
型の実装だと、std::slice::Iter
型を返す。なので、for式はこのIter
型のinto_iter()
を呼ぶことになるが、実装を見るとself
を返しているだけ。Iter
型はIterator
トレイトも実装しているということになる。
let numbers = vec![1];
let mut iterator = numbers.iter();
assert_eq!(iterator.next(), Some(&1));
assert_eq!(iterator.next(), None);
Iter
型のnext()
の実装を見てみたけど、現時点では理解できそうになかった。ただ、上のコードの通り、next()
は要素の不変の参照を返す。一方で、iter_mut()
ではこれが可変の参照になる。