为了账号安全,请及时绑定邮箱和手机立即绑定

iter和into_iter有什么区别?

iter和into_iter有什么区别?

Git
慕码人2483693 2019-11-12 14:02:28
我正在做具有示例代码片段的Rust by Example教程:// Vec examplelet 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 examplelet 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是什么?
查看完整描述

3 回答

?
慕工程0101907

TA贡献1887条经验 获得超5个赞

第一个问题是:“什么是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……三次!


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> { /* ... */ }

}

所以:


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。


查看完整回答
反对 回复 2019-11-12
?
一只甜甜圈

TA贡献1836条经验 获得超5个赞

.into_iter()不是针对数组本身实现的,而仅针对&[]。相比:


impl<'a, T> IntoIterator for &'a [T]

    type Item = &'a T


impl<T> IntoIterator for Vec<T>

    type Item = T

由于IntoIterator仅在上定义&[T],因此切片本身无法像Vec使用值那样被丢弃。(值不能移出)


现在,为什么是这样,这是一个不同的问题,我想学习一下自己。推测:数组是数据本身,切片只是对其的视图。实际上,您不能将数组作为值移动到另一个函数中,只能传递它的视图,因此也不能在那里使用它。


查看完整回答
反对 回复 2019-11-12
  • 3 回答
  • 0 关注
  • 1668 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信