• rust闭包


    rust闭包

    参考

    Rust有三个闭包trait:Fn、FnMut和FnOnce编译器会根据闭包内代码的行为自动为闭包实现这些trait。

    上面这段话超级重要!!!

    1. 对于不可变或移动捕获变量的闭包,编译器会实现Fn trait,这样闭包可以多次调用,甚至可以在多个线程上并行调用
    2. 对于可变捕获变量但不移动它们出闭包的闭包,编译器会实现FnMut trait,这样的闭包可以多次调用,但不能并行调用
    3. 对于会移动捕获变量出闭包的闭包,编译器会实现FnOnce trait,这样的闭包只能调用一次。注意move关键字不影响trait实现,它只是强制移动变量进入闭包

    Fn trait是FnMut的子trait,FnMut trait是FnOnce的子trait。这意味着:

    1. 每个实现Fn trait的闭包也实现了FnMut和FnOnce。任何需要FnMut或FnOnce的地方,都可以传递实现Fn的闭包。
    2. 每个实现FnMut trait的闭包也实现了FnOnce。任何需要FnOnce的地方都可以传递实现FnMut的闭包。

    如果被调用者接受FnOnce,它对闭包能做的事情受到最大限制——它只能调用闭包一次。但是调用者可以自由传递任何闭包,因为所有的闭包都实现了FnOnce,这是由子trait和父trait的关系决定的。

    如果被调用者接受FnMut,那么它对闭包的限制会少一些。现在它可以调用闭包多次,但是仍然不能例如在多个线程上并发地调用闭包,因为那会导致数据共用。相应的,调用者也会受到更多的限制。例如,它不能在闭包中drop一个被捕获的变量或以其他方式将其移出闭包。

    最后,如果被调用者接受Fn,那么它可以无限制的调用闭包,甚至并发调用。与此同时,调用者不能改变闭包中的变量。
    在这里插入图片描述

    最后附上一个学习闭包过程中,关于函数调用不可变String作为形参可变String的例子。

      let a = "fox".to_string();
      let add1=&a;
      println!("{:p}",add1);  // 打印变量的地址
      let b = test1(a);
      println!("{:?}",b);
      println!("{:p}",&b);
    
    }
    
    fn test1(mut s : String)-> String{
      let add2 = &s;
      println!("{:p}",add2);
      s.push_str("123");
      s
    }
    
    PS D:\code\rust\test_demo> cargo run
       Compiling test_demo v0.1.0 (D:\code\rust\test_demo)
        Finished dev [unoptimized + debuginfo] target(s) in 2.51s
         Running `target\debug\test_demo.exe`
    0x119a6ff3a8
    0x119a6ff420
    "fox123"    
    0x119a6ff408
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    
      let a = "fox".to_string();
      let add1=&a;
      println!("{:p}",add1);  // 打印变量的地址
      let b = test1(a);
      println!("{:?}",b);
      println!("{:p}",&b);
    
    }
    
    fn test1(s : String)-> String{
      let add2 = &s;
      println!("{:p}",add2);
      // s.push_str("123");
      s
    }
    
    PS D:\code\rust\test_demo> cargo run
       Compiling test_demo v0.1.0 (D:\code\rust\test_demo)
        Finished dev [unoptimized + debuginfo] target(s) in 0.42s
         Running `target\debug\test_demo.exe`
    0x8758aff458
    0x8758aff4d0
    "fox"       
    0x8758aff4b8
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    实际上a是不可变string,但是test1函数可以捕获a的所有权,然后重新给了一个新的变量s,s是可变的。打印地址可以看出他们的地址都不相同。

  • 相关阅读:
    2022年互联网企业软件测试面试宝典
    获取文件信息和目录操作
    vb.net的日期工具类
    您的系统存在未授权的Bluetooth适配器,拔除或禁用该设备(蓝牙问题)
    java swing(GUI) MySQL实现的学生选课成绩管理系统源码+运行教程
    MyBatis加强(2)~mybatis 插件开发 【分页插件-PageHelper】
    Proxy应用场景
    使用 KubeBlocks 为 K8s 提供稳如老狗的数据库服务
    Kafka - 07 Zookeeper中存储的 Kafka 信息
    查看当前设备是否启用SR-IOV
  • 原文地址:https://blog.csdn.net/qq_40896190/article/details/134181120