TL;DR:
- 根据上下文,由
into_iter
返回的迭代器可能会产生T
、&T
或&mut T
中的任何一个.
- 按照惯例,由
iter
返回的迭代器将产生&T
.
- 按照惯例,由
iter_mut
返回的迭代器将产生&mut T
.
第一个问题是:"什么是into_iter
?"
into_iter
来自IntoIterator
trait:
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
...三次!
impl<T> IntoIterator for Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>
impl<'a, T> IntoIterator for &'a mut Vec<T>
每种变体略有不同.
这个函数消耗Vec
及其迭代器yields values(直接消耗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
中元素的引用.
这个yields immutable references:
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> { /* ... */ }
}
而这个yields mutable references:
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
是获取迭代器的通用方法,无论该迭代器生成值、不可变引用还是可变引用is context dependent,有时都会令人惊讶.
iter
和iter_mut
是临时方法.因此,它们的返回类型独立于上下文,通常是迭代器,分别生成不可变引用和可变引用.
Rust by Example post的作者举例说明了对调用into_iter
的上下文(即类型)的依赖所带来的惊喜,并利用以下事实使问题更加复杂:
IntoIterator
不执行[T; N]
,仅用于&[T; N]
和&mut [T; N]
,它将用于Rust 2021.
- 如果没有为某个值实现某个方法,则会自动搜索该值的references
这对于into_iter
来说非常令人惊讶,因为所有类型([T; N]
除外)都为所有3个变体(值和引用)实现了它.
数组实现了IntoIterator
(以如此惊人的方式),从而可以在for
个循环中迭代对它们的引用.
从Rust 1.51开始,数组可以实现一个迭代器来生成值(通过array::IntoIter
),但现有的IntoIterator
实现会自动引用makes it hard to implement by-value iteration via IntoIterator
.