用rust搞个数据结构-链表3

rust 里面的 for 循环实际上是个迭代器的语法糖。

比如常见的

1
2
3
for i in 1..100 {
todo!();
}

这里我们用 let 绑定一个变量到 1..100 上,利用标准库里的 type_name::() 查看类型信息。

1
2
3
4
5
6
7
8
9
fn type_of<T>(_: &T) -> &'static str{
std::any::type_name::<T>()
}

fn main() {
let i = 1..10;
println!("{}", type_of(&i));
}

编译运行终端的输出为

而标准库中这个泛型类型也实现了与迭代器相关的 trait

在实际编译时 for 循环会被展开成常规的循环。

也正是因为 for 循环的这种特性,任何一个集合类型只要实现了迭代器相关的 trait , 就可以遍历其所有子元素并进行操作。

首先我们来为我们的链表的 IntoIter 结构体实现 Iterator trait

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pub struct IntoIter<T>(List<T>);

impl<T> List<T> {
pub fn into_iter(self) -> IntoIter<T> {
IntoIter(self)
}
}

impl<T> Iterator for IntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
self.0.pop()
}
}

这里我们首先实现了一个元组结构体 IntoIter ,这是一个泛型的结构体,其泛型参数与我们的链表保持一致,然后我们对其实现了 Iterator trait 。这个 trait 里面除了 next() 方法外还有一个关联类型 Item , 在这里我们将其定义为为我们链表的泛型参数。

next() 方法的返回值即为使用 Option 包裹的关联类型。

实现了此 trait 即可使用 into_iter() 方法,注意此方法会消费所有权,绝大多数情况下这种并不常见。

接下来我们为我们的链表实现不获取所有权的 Iter 结构体和对应的 Iterator trait 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pub struct Iter<'a, T> {
next: Option<&'a Node<T>>,
}

impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;

fn next(&mut self) -> Option<Self::Item> {
self.next.map(|node| {
self.next = node.after.as_deref();
&node.elem
})
}
}

由于涉及到数据的借用,这里需要显示的标注出结构体的生命周期,这里满足生命周期省略原则,所以尽管 impl 块上标注了生命周期 'a ,但是 next() 方法并没有标出。

简单来说,在这里返回的借用的生命周期必然短于接受的借用,所以可以认为两者具有相同的生命周期约束 'a,其长短取决于返回借用实际存活的生命周期 。

类似的,返回拥有可变借用的 IterMut 结构体和 Iterator trait也是类似的设计。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
pub struct IterMut<'a, T> {
next: Option<&'a mut Node<T>>,
}

impl<'a, T> Iterator for IterMut<'a, T> {
type Item = &'a mut T;

fn next(&mut self) -> Option<Self::Item> {
self.next.take().map(|node| {
self.next = node.after.as_deref_mut();
&mut node.elem
})
}
}

在剩下的两种迭代器的设计中,我们的代码用到了 as_deref()as_deref_mut() 方法。

这两个方法的目的是将 Option 或其(可变)借用映射成用 Option 包装的包装物,以下为其对应的函数签名。

1
2
3
pub const fn as_deref(&self) -> Option<&T::Target>
where
T: Deref,
1
2
3
pub const fn as_deref_mut(&mut self) -> Option<&mut T::Target>
where
T: DerefMut,

用rust搞个数据结构-链表3
https://ooj2003.github.io/2022/04/02/用rust搞个数据结构-链表3/
作者
OOJ2003
发布于
2022年4月2日
更新于
2022年5月27日
许可协议