iter和into_iter有什么区别?

我正在做具有示例代码片段的Rust by Example教程:


// 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从iteryields引用返回的迭代器和从into_iteryields值返回的迭代器,但是对于数组,这些迭代器是相同的吗?


这两种方法的用例/ API是什么?


慕码人2483693
浏览 1594回答 3
3回答

慕工程0101907

第一个问题是:“什么是into_iter?”into_iter来自IntoIterator特征:pub trait IntoIterator&nbsp;where&nbsp; &nbsp; <Self::IntoIter as Iterator>::Item == Self::Item,&nbsp;{&nbsp; &nbsp; type Item;&nbsp; &nbsp; type IntoIter: Iterator;&nbsp; &nbsp; 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并且它的迭代器产生值(T直接):impl<T> IntoIterator for Vec<T> {&nbsp; &nbsp; type Item = T;&nbsp; &nbsp; type IntoIter = IntoIter<T>;&nbsp; &nbsp; fn into_iter(mut self) -> IntoIter<T> { /* ... */ }}另外两个通过引用获取向量(在两种情况下都不要被into_iter(self)因为self是引用的签名所欺骗),并且它们的迭代器将生成对内部元素的引用Vec。这产生了不可变的参考:impl<'a, T> IntoIterator for &'a Vec<T> {&nbsp; &nbsp; type Item = &'a T;&nbsp; &nbsp; type IntoIter = slice::Iter<'a, T>;&nbsp; &nbsp; fn into_iter(self) -> slice::Iter<'a, T> { /* ... */ }}虽然这产生了可变的参考:impl<'a, T> IntoIterator for &'a mut Vec<T> {&nbsp; &nbsp; type Item = &'a mut T;&nbsp; &nbsp; type IntoIter = slice::IterMut<'a, T>;&nbsp; &nbsp; fn into_iter(self) -> slice::IterMut<'a, T> { /* ... */ }}所以:iter和之间有什么区别into_iter?into_iter是获取迭代器的通用方法,无论该迭代器产生值,不可变引用还是可变引用都是上下文相关的,有时可能令人惊讶。iter并且iter_mut是临时方法。这可以解决上下文相关位,并且按照惯例,您可以获取一个迭代器,该迭代器将产生引用。Rust by Example帖子的作者举例说明了对依赖于所into_iter调用的上下文(即类型)的依赖而产生的惊奇,并且还通过使用以下事实使问题更加复杂:IntoIterator未针对[T; N],仅针对&[T; N]和实现&mut [T; N]如果没有为值实现方法,则会自动搜索该值的引用这是非常令人惊讶的,into_iter因为所有类型(除外[T; N])都为所有3个变体(值和引用)实现了它。数组不可能实现产生值的迭代器,因为它不能“缩小”以放弃其项。关于数组为何实现IntoIterator(以一种令人惊讶的方式):使得有可能在循环中遍历对它们的引用for。

一只甜甜圈

.into_iter()不是针对数组本身实现的,而仅针对&[]。相比:impl<'a, T> IntoIterator for &'a [T]&nbsp; &nbsp; type Item = &'a T与impl<T> IntoIterator for Vec<T>&nbsp; &nbsp; type Item = T由于IntoIterator仅在上定义&[T],因此切片本身无法像Vec使用值那样被丢弃。(值不能移出)现在,为什么是这样,这是一个不同的问题,我想学习一下自己。推测:数组是数据本身,切片只是对其的视图。实际上,您不能将数组作为值移动到另一个函数中,只能传递它的视图,因此也不能在那里使用它。
打开App,查看更多内容
随时随地看视频慕课网APP