我正在做生锈教程,其中包含以下代码片段:
// 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是什么?
发布于 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> { /* . */ }
所以:
iter和into_iter有什么区别?
into_iter是一种获得迭代器的通用方法,不管这个迭代器产生值、不可变引用还是可变引用--是上下文相关的,有时可能会令人惊讶。
iter和iter_mut是一种特殊的方法.因此,它们的返回类型与上下文无关,并且通常是迭代器,分别产生不变的引用和可变的引用。
“锈菌附例”的作者举例说明了对调用into_iter的上下文(即类型)的依赖所带来的惊讶,并利用以下事实使问题更加复杂:
IntoIterator不是为[T; N]实现的,而是为&[T; N]和&mut [T; N]实现的--它将用于Rust 2021年。这对于into_iter来说是非常令人惊讶的,因为所有类型(除了[T; N])都为所有3种变体(值和引用)实现了它。
数组实现IntoIterator (以一种令人惊讶的方式),以便能够在for循环中迭代对它们的引用。
从Rust 1.51开始,数组可以实现一个迭代器来生成值(通过array::IntoIter),但是IntoIterator的现有实现会自动引用IntoIterator。
发布于 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
发布于 2016-01-12 01:02:54
.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相同的方式删除片本身。(值不能移出)
现在,为什么是这样的情况是另一个问题,我想了解自己。推测:数组是数据本身,片只是一个视图。实际上,您不能将数组作为一个值移动到另一个函数中,只需传递它的一个视图,因此您也不能在那里使用它。
https://stackoverflow.com/questions/34733811
复制相似问题