Rust:迭代 iter() 或向量本身

Are*_*ski 8 iterator loops rust

我正在观看 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);
}
Run Code Online (Sandbox Code Playgroud)

Mas*_*inn 9

您能告诉我这里有什么区别吗?

正如 Stargateur 所说,这里没有区别。要知道发生了什么,您只需遵循白兔特征实现:Rust 的for循环“简单地”调用IntoIterator“RHS”。现在,如果我们查看实施者列表

我们可以看到一个实现&Vec

它本身没有记录,但查看它刚刚调用的代码self.iter(),所以在这里我们确实确认了 Stargateur 是正确的,&VecVec::iter做了完全相同的事情

Vec::iter

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

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T
}
Run Code Online (Sandbox Code Playgroud)

所以Vec<T>::iter-> Iter<T>-> Iterator<Item=&a>,这意味着当您使用.iter()向量(或迭代&Vec)时,您会迭代对 items 的不可变引用。而且由于iter采用&self&Vec显然是一个引用),这也意味着迭代仅借用向量,因此一旦完成迭代,向量仍然保持不变。

&mut VecVec::iter_mut

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

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T
}
Run Code Online (Sandbox Code Playgroud)

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

Vec本身

所以我们来讨论这个,如果你扩展定义,你会看到本质上是这样的:

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

    pub fn into_iter(self) -> IntoIter<T, A>
Run Code Online (Sandbox Code Playgroud)

创建一个消耗迭代器,即将每个值移出向量(从开始到结束)的迭代器。调用此函数后该向量将无法使用。

这是不言自明的:如果你Vec直接迭代它会消耗向量,这意味着你之后将无法使用它。

然而,作为回报,它将向量项的所有权移至迭代器中,从而提供了更大的灵活性。