Rust:迭代 iter() 或 vector 本身

Rust: iterating over iter() or vector itself

我正在观看 Rust 讲座,看到我认为有两种迭代向量的方法。我可以遍历“向量本身”或“iter() 方法”。你能告诉我这里有什么区别吗?

fn call(from: &mut Vec<i32>, to: &mut Vec<i32>) {
    for e in from.iter() {
        to.push(*e);
    }
    for e in from {
        to.push(*e);
    }
}

fn printvec(from: & Vec<i32>) {
    for e in from {
        print!("{} ", e);
    }
    println!("");
}

fn main() {
    let mut v1 = vec![1,2,3];
    let mut v2 = vec![1,2,3];
    call(&mut v1, &mut v2);
    printvec(&v1);
    printvec(&v2);
}

来自Rust Reference

'label: for PATTERN in iter_expr {
    /* loop body */
}

is equivalent to

{
    let result = match IntoIterator::into_iter(iter_expr) {
        mut iter => 'label: loop {
            let mut next;
            match Iterator::next(&mut iter) {
                Option::Some(val) => next = val,
                Option::None => break,
            };
            let PATTERN = next;
            let () = { /* loop body */ };
        },
    };
    result
}

for 循环之间的区别在于,在一个循环中 iter_exprfrom,在另一个循环中是 from.iter()IntoIterator 是这样实现的矢量参考:

impl<'a, T, A: Allocator> IntoIterator for &'a Vec<T, A> {
    type Item = &'a T;
    type IntoIter = slice::Iter<'a, T>;

    fn into_iter(self) -> slice::Iter<'a, T> {
        self.iter()
    }
}

请注意,它正在调用 self.iter(),因此此迭代器与您从 from.iter() for 循环中获得的迭代器没有区别。

Could you please tell me what is the difference here?

正如 Stargateur 所说,这里没有区别。要知道发生了什么,您只需遵循 white rabbit trait 实现:Rust 的 for 循环“简单地”调用 IntoIterator on the "RHS". Now if we go down the list of implementors

我们可以看到an implementation for &Vec

它本身没有记录,但是 looking at the code it just calls self.iter(),所以我们在这里确认 Stargateur 是正确的,&VecVec::iter 做完全相同的事情

Vec::iter

文档有点简洁,但它链接到 std::slice::Iter,它是“不可变切片迭代器”,本身不一定非常有用 ,但 特征实现很清楚

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

所以 Vec<T>::iter -> Iter<T> -> Iterator<Item=&a>,意思是当你 .iter() 一个向量(或者你迭代一个 &Vec)你迭代对项目的不可变引用。并且由于 iter 采用 &self (并且 &Vec 显然是一个参考)这也意味着迭代仅 借用 向量,所以一旦你'完成迭代后,向量仍然保持不变。

&mut VecVec::iter_mut

虽然你没有提到它是第二个迭代器,但它与上面的迭代器类似,只是它产生了一个 std::slice::IterMut

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

所以不是生成对项目的不可变引用,而是生成可变引用,这意味着您可以就地修改项目,例如增加它们,很酷。

Vec itself

所以我们来到这里,如果您扩展定义,您基本上会看到:

impl<T> IntoIterator for Vec<T> {
    type Item = T
    type IntoIter = IntoIter<T, A>

    pub fn into_iter(self) -> IntoIter<T, A>

Creates a consuming iterator, that is, one that moves each value out of the vector (from start to end). The vector cannot be used after calling this.

这是不言自明的:如果你直接迭代 Vec 消耗 向量,这意味着你 不会 之后就可以使用了。

但是,在 return 中,它 将向量项的所有权 移动到迭代器中,这提供了更大的灵活性。