Catalyst

Rust 笔记(八)闭包和 move

闭包

Rust 的闭包 (closure) 是匿名函数,可以将其保存在变量中或作为参数传递给其他函数。

fn main() {
    let closure = |x| x*x;
    assert_eq!(closure(3),9);
}

虽然闭包没有标注变量类型,编译器会根据使用的类型推断,使用不同的类型不会编译通过。

闭包可以通过三种方式获取环境中的值:

  1. 不可变借用
  2. 可变借用
  3. 获取所有权
fn main() {
    // 1. 不可变借用
    let data = "不变数据".to_string();

    let immutably_borrow = || println!("data: {data}");

    println!("不可变借用:");
    immutably_borrow();

    // 2. 可变借用
    let mut mut_data = "可变数据".to_string();

    let mut mut_borrow = || {mut_data.push('+');println!("data: {mut_data}");};

    // 在使用可变借用前,不能再使用不变借用,取消下一行注释会报错:cannot borrow `mut_data` as immutable because it is also borrowed as mutable
    // println!("data: {mut_data}");

    println!("可变借用:");
    mut_borrow();
}

Move

资源同时只能有一个所有者,资源的所有权转移后,前所有者将不能再被使用,防止出现悬空指针(Dangling Pointer)。

move的作用是按值捕获闭包的环境,move将通过引用或可变引用捕获的任何变量转换为按值捕获的变量。

例子:

fn main() {
    let data = vec![1, 2, 3];

    // 不会打印
    let closure = move || println!("捕获 {data:?}");

    // data 将不可用,不注释下行会出现编译错误:value borrowed here after move
    // println!("print {data:?}");

    // 在这里打印
    println!("指示位置用 ↓");
    closure();
}

注意:move 闭包仍然可以实现 FnFnMut,即使它们通过 move 捕获变量。这是因为闭包类型实现的特征取决于闭包对捕获值的作用,而不是它如何捕获它们:

Fn 特性

待续