fn main() {
let v = vec![1, 2, 3];
for i in v {
println!("{}",i);
}
let v = vec![1, 2, 3];
{
let mut iter = v.into_iter();
loop {
match iter.next() {
Some(i) => {
println!("{}",i);
}
None => break,
}
}
}
}
Iterator Trait
可以看到将Iter结构说的很清楚了,通过上面自己实现的迭代器
This module is largely organized by type:
Traits are the core portion: these traits define what kind of iterators exist and what you can do with them. The methods of these traits are worth putting some extra study time into.
Functions provide some helpful ways to create some basic iterators.
Structs are often the return types of the various methods on this module's traits. You'll usually want to look at the method that creates the struct, rather than the struct itself. For more detail about why, see 'Implementing Iterator'.
pub trait IntoIterator
where
<Self::IntoIter as Iterator>::Item == Self::Item,
{
type Item;
type IntoIter: Iterator;
fn into_iter(self) -> Self::IntoIter;
}
impl<T> IntoIterator for Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>
impl<'a, T> IntoIterator for &'a mut Vec<T>
从上面看有三种不同的迭代器
· IntoIter,转移所有权,对应self。
· Iter,获得不可变借用,对应&self。
· IterMut,获得可变借用,对应&mut self。
底下是关于数组源码中定义在impl [T]中的方法,可以看到都有统一的行为
pub struct Iter<'a, T: 'a> {
ptr: NonNull<T>,
end: *const T, // If T is a ZST, this is actually ptr+len. This encoding is picked so that
// ptr == end is a quick test for the Iterator being empty, that works
// for both ZST and non-ZST.
_marker: marker::PhantomData<&'a T>,
}
pub fn iter(&self) -> Iter<'_, T> {
unsafe {
let ptr = self.as_ptr();
assume(!ptr.is_null());
let end = if mem::size_of::<T>() == 0 {
(ptr as *const u8).wrapping_add(self.len()) as *const T
} else {
ptr.add(self.len())
};
Iter { ptr: NonNull::new_unchecked(ptr as *mut T), end, _marker: marker::PhantomData }
}
}
//collect::IntoIterator for &[T; _]
impl<'a, T, const N: usize> IntoIterator for &'a [T; N]
where
[T; N]: LengthAtMost32,
{
type Item = &'a T;
type IntoIter = Iter<'a, T>;
fn into_iter(self) -> Iter<'a, T> {
self.iter()
}
}
迭代器适配器
可以看到还有一堆 Struct 没讲,大部分都是适配器
#[must_use = "iterators are lazy and do nothing unless consumed"]表明适配器是惰性的
如果没有对迭代器产生任 何“消费”行为,它是不会发生真正的迭代的
#[must_use = "iterators are lazy and do nothing unless consumed"]
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Filter<I, P> {
iter: I,
predicate: P,
}
impl<I, P> Filter<I, P> {
pub(super) fn new(iter: I, predicate: P) -> Filter<I, P> {
Filter { iter, predicate }
}
}
Iter
是平常用的最多了, 没事瞅瞅迭代器模式
才了解到迭代器是一种设计模式(design pattern) ,我太菜了
遍历集合中的元素而不暴露底层实现,这里又涉及到内部迭代器和外部迭代器
可以看rust 早期拥有内部迭代器container: remove internal iterators from Map
自定义一个简单内部迭代器,内部迭代器传入元素和操作闭包之后就无法再进行操作,必须等遍历完才能够停下,中间没办法对迭代器进行操作
现在为了更灵活,采用外部迭代器.自己自定义实现了一个外部迭代器
for 循环也是个外部迭代器的语法糖
Iterator Trait
可以看到将
Iter
结构说的很清楚了,通过上面自己实现的迭代器用Iterator trait 定义方法
IntoIterator Trait
接下来就是转换成迭代器
不同类型转换为
Iter
定一个不同的IntoIter
结构体 并且被Iterator
Trait 绑定,拥有next
等方法例如
Vec
距离, 具体如下图从上面看有三种不同的迭代器
底下是关于数组源码中定义在
impl [T]
中的方法,可以看到都有统一的行为迭代器适配器
可以看到还有一堆 Struct 没讲,大部分都是适配器
#[must_use = "iterators are lazy and do nothing unless consumed"]
表明适配器是惰性的 实现也很简单,相当于传入迭代器和一个方法(闭包),表明拥有的行为,为啥是惰性的.可以理解为你虽然有这个方法,但是你得去调用才能去执行.
消费器
去使用迭代器里面的方法叫做消费器,比如
next()
就是消费器,遍历迭代器里的元素.实现没啥难的= =等以后有啥不明白的再回来补吧 (摸了