【问题标题】:When should I use function pointers instead of closures?什么时候应该使用函数指针而不是闭包?
【发布时间】:2021-12-06 15:36:54
【问题描述】:
我的理解是,实现一个以impl Fn 作为参数的函数允许 rust 编译器执行更多优化,但使用 impl Fn 而不是函数指针不应该更具限制性。
我还可以将函数指针传递给接受impl Fn 的函数,所以我猜测Rust 中的函数指针类型仅可用作PhantomData 的通用参数来表达类型差异,在ffi 和某些情况下作为Box<dyn Fn(...) -> ...>的替代品。
【问题讨论】:
标签:
rust
closures
function-pointers
【解决方案1】:
-
impl Fn 类型基本上隐藏了类型参数。使函数成为泛型函数的任何类型参数都需要为传入的每个不同类型重新编译(单态化)函数。因此,与仅采用具体类型(例如,此处的函数指针)的非泛型函数相比,泛型函数会导致更长的编译时间和更多生成的代码。因此,您可以使用函数指针来减少项目的总编译时间或二进制文件的大小。
-
如果您需要存储提供的函数,impl Fn() 意味着将其放入Box<dyn Fn()>,并通过 vtable 调用它。这是比直接调用函数指针多一种间接方式(多一种内存访问)。函数指针可以直接存储在数据结构中,例如Vec<fn(&mut Foo)>.
(但这并不意味着Box 将执行分配;如果函数类型不是捕获闭包(相当于“可以强制为函数指针”),那么它是零-sized 类型,因此 Box 不会分配。)
-
正如您已经指出的,函数指针出现在 FFI 中是因为它们是预期的 ABI,而 impl Fn 或 dyn Fn 是 Rust 特定的。