• Rust for循环语法糖背后的API


    rust有三种for循环,分别用于不同的场景。

    1.拿走所有权的for循环

    形式如:for item in collection(集合或容器类型)会拿走collection的所有权(ownership)

    fn main() {
        let collection: Vec<i32> = vec![1, 2, 4, 6, 9];
    
        // 注意这儿的item类型是i32
        for item in collection {
            println!("item:{}", item);
        }
    
        // for循环之后,不能再使用collection,因为collection的所有权已经被拿走,且在for循环后collection已经被drop掉了
        // println!("collection:{:?}", collection);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    因为rust编译器会将for item in collection替换成for item in IntoIterator::into_iter(collection)

    fn main() {
        let collection: Vec<i32> = vec![1, 2, 4, 6, 9];
    
        // rust中的into_开头的方法一般情况下都会拿走参数的所有权
        let iter = IntoIterator::into_iter(collection);
        // 从这儿开始,collection已经不能再被使用,因为collection的所有权被转移到into_iter方法中,当方法执行完,collection就被drop掉了 
        // println!("collection:{:?}", collection); // 如果这儿使用collection就会编译报错
        for item in iter{
            println!("item:{}", item);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    正如Rust官网https://doc.rust-lang.org/std/iter/trait.IntoIterator.html上说的:One benefit of implementing IntoIterator is that your type will work with Rust’s for loop syntax.,即实现IntoIterator trait能够让你自定义类型在for循环中使用。

    Vec正是实现了IntoIterator,所以才可以在for循环中使用的:
    在这里插入图片描述

    2.只读for循环

    形式如:for item in &collection,不会拿走collection的所有权,只会获取它的不可变引用:

    fn main() {
        let collection: Vec<i32> = vec![1, 2, 4, 6, 9];
    
        // 注意这儿item的类型是&i32,即它是对collection中元素的不可变引用
        for item in &collection {
            println!("item:{}", item);
        }
    
        println!("collection after for loop:{:?}", collection);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    因为rust会将for item in &collection替换成for item in collection.iter():

    fn main() {
        let collection: Vec<i32> = vec![1, 2, 4, 6, 9];
    
        // 注意这儿item的类型是&i32,即它是对collection中元素的不可变引用
        for item in collection.iter() { // 等价于for item in (&collection).iter() {
            println!("item:{}", item);
        }
    
        println!("collection after for loop:{:?}", collection);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    迭代完集合中的元素后,集合还可以继续使用。

    3.读写for循环

    形式如:for item in &mut collection,不会拿走collection的所有权,只会获取它的可变引用:

    fn main() {
        // 注意,为了修改collection中的元素,collection本身必须声明为mut
        let mut collection: Vec<i32> = vec![1, 2, 4, 6, 9];
    
        // 注意这儿item的类型是&mut i32,即它是对collection中元素的可变引用
        for item in &mut collection {
            // 通过*对可变引用进行解引用,从而可以修改引用指向的值
            *item = *item +1;
            println!("item:{}", item);
        }
    
        println!("collection after for loop:{:?}", collection);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    上面的程序运行输出:

    item:2
    item:3
    item:5
    item:7
    item:10
    collection after for loop:[2, 3, 5, 7, 10]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    实现了对集合元素的修改。

    因为rust会将for item in &mut collection替换成for item in collection.iter_mut():

    fn main() {
        // 注意,为了修改collection中的元素,collection本身必须声明为mut
        let mut collection: Vec<i32> = vec![1, 2, 4, 6, 9];
    
        // 注意这儿item的类型是&mut i32,即它是对collection中元素的可变引用
        for item in collection.iter_mut() { // 等价于for item in (&mut collection).iter_mut() {
            // 通过*对可变引用进行解引用,从而可以修改引用指向的值
            *item = *item +1;
            println!("item:{}", item);
        }
    
        println!("collection after for loop:{:?}", collection);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    参考资料:
    1.《Rust实战》(Rust In Action)

  • 相关阅读:
    MyBatis环境配置及查询操作
    神经网络和图神经网络,神经网络 图像相似度
    svn服务支持网页显示并增加在线预览功能,支持视频在线播放,可在公司内部作为文档管理使用
    【数据结构--八大排序】之快速排序
    Ajax入门及jQuery库对Ajax的封装
    python进阶1:魔术方法
    Ubuntu安装Python环境(使用VSCode)
    面试官:关于网络IO模型的原理如何理解,说说你的分析
    python 打包可执行文件-pyinstaller详解
    【Factory模式】C++设计模式——工厂模式
  • 原文地址:https://blog.csdn.net/lzufeng/article/details/127707366