首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >iter和into_iter有什么区别?

iter和into_iter有什么区别?
EN

Stack Overflow用户
提问于 2016-01-12 00:48:51
回答 4查看 98.8K关注 0票数 404

我正在做生锈教程,其中包含以下代码片段:

代码语言:javascript
复制
// 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生成值返回的迭代器会产生值,但是对于数组,这些迭代器是相同的吗?

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2016-01-12 14:08:41

TL;DR:

  • into_iter返回的迭代器可能产生任何T&T&mut T,这取决于上下文。
  • iter返回的迭代器将按照约定生成&T
  • iter_mut返回的迭代器将按照约定生成&mut T

第一个问题是:“into_iter是什么?”

into_iter来自特性

发布特性IntoIterator,其中::Item == Self::Item,{ type Item;键入IntoIter: Iterator;fn into_iter(self) -> Self::IntoIter;}

当您希望指定如何将特定类型转换为迭代器时,可以实现此特性。最值得注意的是,如果一个类型实现了IntoIterator,那么它可以在for循环中使用。

例如,Vec实现IntoIterator..。三次!

impl for Vec impl<'a,T> IntoIterator for &'a IntoIterator for &a mut Vec

每个变体略有不同。

它使用Vec及其迭代器 (直接使用T):

用于Vec { type IntoIterator = T;type IntoIter = IntoIter;fn into_iter(mut self) -> IntoIter { /* . */ }

另外两个通过引用获取向量(不要被into_iter(self)的签名所欺骗,因为在这两种情况下,self都是引用),它们的迭代器将生成对Vec中元素的引用。

这个不可变引用

impl<'a,T> IntoIterator for &'a Vec { type Item = &'a T;type IntoIter = slice::Iter<'a,T>;fn into_iter(self) ->片::Iter<‘a,T> { /* . */ }

而这个可变引用

impl<'a,T> IntoIterator for &“mut Vec { type Item = &'a mut T;type IntoIter = slice::IterMut<'a,T>;fn into_iter(self) ->片::IterMut<‘a,T> { /* . */ }

所以:

iterinto_iter有什么区别?

into_iter是一种获得迭代器的通用方法,不管这个迭代器产生值、不可变引用还是可变引用--是上下文相关的,有时可能会令人惊讶。

iteriter_mut是一种特殊的方法.因此,它们的返回类型与上下文无关,并且通常是迭代器,分别产生不变的引用和可变的引用。

“锈菌附例”的作者举例说明了对调用into_iter的上下文(即类型)的依赖所带来的惊讶,并利用以下事实使问题更加复杂:

  1. IntoIterator不是为[T; N]实现的,而是为&[T; N]&mut [T; N]实现的--它将用于Rust 2021年。
  2. 当方法未为值实现时,将自动搜索对该值的引用。

这对于into_iter来说是非常令人惊讶的,因为所有类型(除了[T; N])都为所有3种变体(值和引用)实现了它。

数组实现IntoIterator (以一种令人惊讶的方式),以便能够在for循环中迭代对它们的引用。

从Rust 1.51开始,数组可以实现一个迭代器来生成值(通过array::IntoIter),但是IntoIterator的现有实现会自动引用IntoIterator

票数 389
EN

Stack Overflow用户

发布于 2019-08-28 17:45:01

我是从谷歌来这里的,我想要一个简单的答案,而其他答案却没有提供。以下是一个简单的答案:

  • iter()通过引用遍历项。
  • iter_mut()对项进行迭代,为每个项提供可变的引用。
  • into_iter()遍历项目,将它们移动到新的范围中。

因此,for x in my_vec { ... }本质上等同于my_vec.into_iter().for_each(|x| ... ) --两者都将my_vec的元素放入...范围。

如果您只需要查看数据,使用iter,如果您需要编辑/修改它,使用iter_mut,如果您需要给它一个新的所有者,使用into_iter

这很有帮助:http://hermanradtke.com/2015/06/22/effectively-using-iterators-in-rust.html

票数 274
EN

Stack Overflow用户

发布于 2016-01-12 01:02:54

.into_iter()不是为数组本身实现的,而是只为&[]实现的。比较:

代码语言:javascript
复制
impl<'a, T> IntoIterator for &'a [T]
    type Item = &'a T

使用

代码语言:javascript
复制
impl<T> IntoIterator for Vec<T>
    type Item = T

由于IntoIterator仅在&[T]上定义,所以当您使用这些值时,不能以与Vec相同的方式删除片本身。(值不能移出)

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

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34733811

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档