迭代器和所有权

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.