微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Rust:迭代 iter() 或 vector 本身 我们可以看到an implementation for &VecVec::iter&mut Vec 和 Vec::iter_mutVec itself

如何解决Rust:迭代 iter() 或 vector 本身 我们可以看到an implementation for &VecVec::iter&mut Vec 和 Vec::iter_mutVec 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,3];
    call(&mut v1,&mut v2);
    printvec(&v1);
    printvec(&v2);
}

解决方法

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

这里与 Stargateur 指出的没有区别。要知道发生了什么,您只需遵循 white rabbit trait 实现:Rust 的 for 循环“简单地”调用“RHS”上的 IntoIterator。现在如果我们往下走 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>

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

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

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

,

来自Rust Reference

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

相当于

{
    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 循环中获得的迭代器没有区别。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。