似乎有两种方法可以将函数作为参数传递,而不进行动态分配:
&impl Fn(TIn) -> TOut // By referenceimpl Fn(TIn) -> TOut // By value假设函数是纯函数(即可以多次调用),我最初的想法是最好的方法是通过引用传递。这意味着一个函数对象可以多次使用(因为所有权不会转移),在更常见的情况下,它只是一个匿名闭包,应该优化引用的间接引用,因为编译器完全知道函数本身(因此可以内联)。
但是,Option::map例如,我注意到按值传递了它的关闭,这让我觉得也许我做错了什么。
我应该按值还是按引用传递函数对象?如果两种方法都没有明确的答案,我应该考虑哪些因素?
TL; DR:您应该使用F: Fn() -> ()或impl Fn() -> ()作为参数。
Fn正如@Bubletan提到在他们的答案,关键的一点是,Fn被自动执行的&F,如果F工具Fn:
impl<'_, A, F> Fn<A> for &'_ F
where
F: Fn<A> + ?Sized,
Run Code Online (Sandbox Code Playgroud)
结果是:
foo(f: impl Fn() -> ())可以同时用foo(callable)或调用foo(&callable)。foo(f: &impl Fn() -> ()) 强制呼叫者使用foo(&callable)和禁止foo(callable)。通常,最好在被呼叫者有缺点时将选择权留给呼叫者,因此应首选第一种形式。
FnMut同样的逻辑适用于FnMut,它也自动地实现为&mut F如果F工具FnMut:
impl<'_, A, F> FnMut<A> for &'_ mut F
where
F: FnMut<A> + ?Sized,
Run Code Online (Sandbox Code Playgroud)
因此,还应该在参数中通过值传递该参数,从而让调用者可以选择是否更喜欢foo(callable)或foo(&mut callable)。
FnOnce存在与保持一致的参数,FnOnce只能通过值传递,这再次指向按值获取Fn*家庭参数的方向。
| 归档时间: |
|
| 查看次数: |
126 次 |
| 最近记录: |