MST
星途 面试题库

面试题:Rust闭包的捕获方式及应用场景

请阐述Rust闭包有哪些捕获环境变量的方式,并分别举例说明在什么实际场景下会使用到这些捕获方式。
17.1万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

Rust闭包捕获环境变量有以下三种方式:

  1. 按值捕获(Copy语义)

    • 当闭包捕获的环境变量实现了Copy trait时,闭包会按值捕获这些变量。
    • 示例
    fn main() {
        let x = 5;
        let closure = || {
            println!("The value of x is: {}", x);
        };
        closure();
    }
    
    • 实际场景:当你希望闭包持有一份独立的环境变量副本,并且这个变量类型实现了Copy,比如基本整数类型、f32f64等。例如,在一个函数中,你想基于某个局部变量的值创建一个闭包用于后续的计算,但又不想这个闭包对原变量有任何副作用,就可以按值捕获。
  2. 按引用捕获(不可变引用)

    • 闭包会捕获环境变量的不可变引用。如果闭包只需要读取环境变量的值,而不需要修改它,就会按不可变引用捕获。
    • 示例
    fn main() {
        let mut x = 5;
        let closure = || {
            println!("The value of x is: {}", x);
        };
        closure();
        println!("After closure, x is: {}", x);
    }
    
    • 实际场景:在迭代器的filtermap等方法中经常使用。例如,你有一个结构体实例,你想在迭代器操作中基于这个结构体的某个字段来过滤元素,就可以按不可变引用捕获这个结构体实例。
    struct Config {
        threshold: i32
    }
    fn main() {
        let config = Config { threshold: 5 };
        let numbers = vec![1, 2, 3, 6, 7];
        let result = numbers.iter().filter(|&num| num > config.threshold).collect::<Vec<_>>();
        println!("{:?}", result);
    }
    
  3. 按可变引用捕获

    • 闭包捕获环境变量的可变引用,允许闭包修改捕获的变量。
    • 示例
    fn main() {
        let mut x = 5;
        let closure = || {
            x += 1;
            println!("The new value of x is: {}", x);
        };
        closure();
    }
    
    • 实际场景:当你需要在闭包内部修改环境变量的值时。比如,在实现一个计数器功能,在闭包内每次调用时更新计数器的值。
    fn main() {
        let mut count = 0;
        let increment = || {
            count += 1;
            count
        };
        println!("First call: {}", increment());
        println!("Second call: {}", increment());
    }