迭代器和所有权
Rust 的所有权模式会影响许多 API。例如,“Iterator”和“IntoIterator” trait。
“Iterator”
trait 类似于接口:它们描述某类型的行为(方法)。“Iterator”trait 只是告知您可以调用“next”,直到返回“None”:
#![allow(unused)] fn main() { pub trait Iterator { type Item; fn next(&mut self) -> Option<Self::Item>; } }
您可以按如下方式使用此 trait:
fn main() { let v: Vec<i8> = vec![10, 20, 30]; let mut iter = v.iter(); println!("v[0]: {:?}", iter.next()); println!("v[1]: {:?}", iter.next()); println!("v[2]: {:?}", iter.next()); println!("No more items: {:?}", iter.next()); }
迭代器返回的类型是什么?请在此测试您的答案:
fn main() { let v: Vec<i8> = vec![10, 20, 30]; let mut iter = v.iter(); let v0: Option<..> = iter.next(); println!("v0: {v0:?}"); }
为什么要使用此类型?
“IntoIterator”
“Iterator”trait会告知您在创建迭代器后如何进行迭代。相关 trait“IntoIterator”会告知您如何创建迭代器:
#![allow(unused)] fn main() { pub trait IntoIterator { type Item; type IntoIter: Iterator<Item = Self::Item>; fn into_iter(self) -> Self::IntoIter; } }
这里的语法表示,“IntoIterator”的每个实现都必须声明两种类型:
- “Item”:我们迭代的类型,例如“i8”,
- “IntoIter”:“into_iter”方法返回的“Iterator”类型。
Note that IntoIter
and Item
are linked: the iterator must have the same Item
type, which means that it returns Option<Item>
和之前一样,迭代器返回的类型是什么?
fn main() { let v: Vec<String> = vec![String::from("foo"), String::from("bar")]; let mut iter = v.into_iter(); let v0: Option<..> = iter.next(); println!("v0: {v0:?}"); }
“for”循环
现在,我们已了解了“Iterator”和“IntoIterator”,接下来可以构建“for”循环了。它们会针对表达式调用“into_iter()”,并对生成的迭代器进行迭代:
fn main() { let v: Vec<String> = vec![String::from("foo"), String::from("bar")]; for word in &v { println!("word: {word}"); } for word in v { println!("word: {word}"); } }
每个循环中的“word”是什么类型?
Experiment with the code above and then consult the documentation for impl IntoIterator for &Vec<T>
and impl IntoIterator for Vec<T>
to check your answers.