[Rust]三种iterator使用说明

本文探讨Rust中的迭代器,特别是它们与所有权、不可变引用和可变引用的关系。通过`Iterator`接口的`next()`方法,解释如何判断迭代是否结束。文章介绍了创建迭代器的三种方式:`iter()`, `iter_mut()`和`into_iter()`,以及它们对向量的不同需求:不可变引用、可变引用和所有权转移。通过示例代码,展示了不同迭代器返回值的差异,并通过错误信息验证了所有权的转移。" 29370629,2444991,修复MFC应用在DPI缩放后的界面错误与崩溃问题,"['C++', 'Windows开发', 'GUI编程', 'DPI感知', 'MFC应用']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Rust中使用变量的途径有三种,所有权(ownership), 不可变引用(immutable reference) 和可变引用(mutable reference)。如果学习了Rust,我们会发现这三种使用值的办法充斥着Rust的角角落落。在此,我们来研究一下Rust Iterator,及其与这三种方式的联系。

首先,所有的迭代器都实现了Iterator Trait,而next方法无疑是Iterator Trait中最基本的方法。我们来看下它的方法签名:


pub trait Iterator {
    type Item;

    fn next(&mut self) -> Option<Self::Item>;
 
}
来自:https://kaisery.github.io/trpl-zh-cn/ch13-02-iterators.html

我们可以看到,next方法的参数是&mut self,也就是可变的迭代器引用。因此,call next方法的类型一定是一个可变的迭代器,不可变迭代器不能call next方法。

next方法的返回值是Option<Self::Item>这个enum,目的是可以让我们判断是否有next value。如果有下一个值,那么返回值就是Some<Item Type>,如果没有下一个值,那么返回值就是None。我们可以通过match来判断。

现在我们来看Vec<T>生成迭代器的办法。有三种方式可以实现这个目的,分别是iter,iter_mutinto_iter。根据我的理解,这三种方法分别需要Vec<T>&self, &mut selfself,即向量的不可变引用,可变引用和向量的所有权。当然了,需要所有权的方法,会move原向量的所有权,所以原向量不再能够使用。

这三个方法生成的迭代器有什么区别呢?根据我的理解,就是在实现Iterator Trait的时候,这三种迭代器的associated type,即关联类型不一样。这就会导致调用next方法的时候:

  1. iter返回的是值的不可变引用,即&T
  2. iter_mut返回的是可变引用,即&mut T
  3. into_iter返回的是T类型的值

让我们来写代码验证我们的猜想。首先来看into_iter

  let v = vec![String::from("good")];
    for mut i in v.into_iter() {
        i.push_str(" morning");
        println!("{}",i);
    }
    println!("{:?}",v);
3 |     for mut i in v.into_iter() {
  |                  - value moved here
...
7 |     println!("{:?}",v);
  |                     ^ value borrowed here after move


通过报错信息我们可以看到,v的所有权已经被move了,不再拥有向量的所有权。如果我们注释掉最后一句,则可以正常使用。因为我们用mut i来代表mut String,所以我们可以改变String的值。

   let v = vec![String::from("good")];
    for mut i in v.into_iter() {
        i.push_str(" morning");
        println!("{}",i);
    }
good morning
   let v = vec![1];
    for i in v.iter() {
        assert_eq!(i, &1);
    }

通过assert_eq!这个宏,我们可以验证,i就是&1

    let v = vec![1];
    for i in v.into_iter() {
        assert_eq!(i, 1);
    }

而通过assert_eq!这个宏,我们可以验证,此时i1

   let mut v = vec![1];
    for i in v.iter_mut() {
        *i = 555;
    }
    println!("{:?}",v);

这段代码的运行结果是:

[555]

实际上,根据我们的分析,这里的i的类型是&mut i32,所以解引用之后可以改变其值。同时,iter_mut只需要&mut self而不是所有权,所以后面还可以正常使用v

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值