Rust函数高级
1. 函数指针(Function Pointers)
在 Rust 中,函数本身也可以作为值传递,这就是 函数指针 的用法。
fn add_one(x: i32) -> i32 {
x + 1
}
// f 是一个函数指针,类型是 fn(i32) -> i32
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
f(arg) + f(arg)
}
- 函数 add_one 可以作为参数传入 do_twice。
- 调用 do_twice(add_one, x) 会执行 add_one(x) 两次并相加。
- 类型写作 fn(i32) -> i32,表示 函数指针类型。
特点:函数指针实现了闭包 trait:Fn、FnMut 和 FnOnce。因此可以在期望闭包的地方直接传入函数。
2. 闭包与函数指针的互换
Rust 中的闭包和函数指针可以互换使用,但闭包可以捕获环境变量,函数指针不能。
let list_of_numbers = vec![1, 2, 3];
// 使用闭包
let list_of_strings_1: Vec<String> = list_of_numbers
.iter()
.map(|x| x.to_string())
.collect();
// 使用函数指针
let list_of_strings_2: Vec<String> = list_of_numbers
.iter()
.map(ToString::to_string)
.collect();
3. 返回闭包的问题与解决方案
尝试直接返回闭包会报错:
// 错误示例
fn return_closure() -> Fn(i32) -> i32 {
|x| x + 1
}
- 原因:Rust 不知道闭包的具体大小(闭包类型是匿名的,不是固定类型)
- 解决办法:使用 动态分发(trait 对象) 和 堆分配:
fn return_closure() -> Box<dyn Fn(i32) -> i32> {
Box::new(|x| x + 1)
}
- Box<dyn Fn(i32) -> i32>:堆上存储闭包,编译器通过 trait 对象动态分发调用
- 这样就可以返回闭包并在函数外使用:
let closure = return_closure();
let y = closure(1);