美文网首页
Rust 闭包初探

Rust 闭包初探

作者: Kernholz | 来源:发表于2022-03-07 20:51 被阅读0次

    Rust 中的闭包

    Rust 中的闭包(closure)是一类特殊的函数。与普通函数相比,闭包是匿名的(当然你可以把闭包赋值给一个变量);更重要的是,闭包可以从其被定义的作用域中捕获变量。

    闭包的类型

    在将闭包作为参数进行传递时,需要标注闭包的类型(实际上是 trait)。一共有三种类型:

    • Fn,表示可以多次调用,但不修改捕获的变量(捕获为不可变引用);
    • FnMut,表示可以多次调用,且可能会修改捕获的变量(捕获为可变引用);
    • FnOnce,表示只保证单次调用的可用性。

    move 关键字

    在闭包前加上 move 关键字,会将闭包的捕获方式从默认的引用捕获变为值捕获。

    需要注意的是,使用了 move 的闭包依然可以实现 FnFnMut,这是因为闭包的类型取决于该闭包如何对捕获的变量进行操作,而不取决于它当初是如何捕获这些变量的。

    fn main() {
        let mut a = 0;
    
        let mut fnmut = move || {
            a += 1;
            println!("Inner: {}", a);
        };
    
        fnmut();
        println!("Outer: {}", a);
    
        fnmut();
        println!("Outer: {}", a);
    }
    

    在上面的例子中,最后的输出是:

    Inner: 1
    Outer: 0
    Inner: 2
    Outer: 0
    

    也即闭包 fnmut 内部的 a 和主函数 main() 中的 a 是两个独立的变量。

    需要注意的是,这里实际上隐式地进行了一次 copy。如果捕获的量没有实现 Copy,则会进行 move,此时对应的量就不能再在外部环境中调用了。例如下面的例子:

    fn main() {
        let data = vec![1, 2, 3];
    
        std::thread::spawn(move || {
            println!("captured {:?} by value", data)
        }).join().unwrap();
    
        println!("{:?}", data);
    }
    

    就会报错

    error[E0382]: borrow of moved value: `data`
     --> src/main.rs:8:22
      |
    2 |     let data = vec![1, 2, 3];
      |         ---- move occurs because `data` has type `Vec<i32>`, which does not implement the `Copy` trait
    3 | 
    4 |     std::thread::spawn(move || {
      |                        ------- value moved into closure here
    5 |         println!("captured {:?} by value", data)
      |                                            ---- variable moved due to use in closure
    ...
    8 |     println!("{:?}", data);
      |                      ^^^^ value borrowed here after move
      |
      = note: this error originates in the macro `$crate::format_args_nl` (in Nightly builds, run with -Z macro-backtrace for more info)
    

    相关文章

      网友评论

          本文标题:Rust 闭包初探

          本文链接:https://www.haomeiwen.com/subject/clynrrtx.html