繁体   English   中英

fn item 和 fn 指针之间的实际区别是什么?

[英]What's the practical difference between fn item and fn pointer?

fn func(_: i64) -> bool {
    true
}

fn func_of_func(callback: &fn(i64) -> bool, arg: i64) -> bool {
    (*callback)(arg)
}

fn main() {
    let is_positive = &func;
    println!("{}", func_of_func(is_positive, 8));
    println!("{}", func_of_func(is_positive, 8));
}

这不编译:

error[E0308]: mismatched types
 --> src/main.rs:9:33
  |
9 |     println!("{}", func_of_func(is_positive, 8));
  |                                 ^^^^^^^^^^^ expected fn pointer, found fn item
  |
  = note: expected reference `&fn(i64) -> bool`
             found reference `&fn(i64) -> bool {func}`

为什么在我传递指针而不是fn会发生此错误? 我想知道使用fn和指向fn指针之间的实际区别。

你应该能够解决这个问题

fn func_of_func(callback: &fn(i64) -> bool, arg: i64) -> bool {
    (*callback)(arg)
}

fn main() {
    let is_positive = func;
    println!("{}", func_of_func(&is_positive, 8));
    println!("{}", func_of_func(&is_positive, 8));
}

或者更直接地通过不添加间接级别

fn func_of_func(callback: fn(i64) -> bool, arg: i64) -> bool {
    callback(arg)
}

fn main() {
    let is_positive = func;
    println!("{}", func_of_func(is_positive, 8));
    println!("{}", func_of_func(is_positive, 8));
}

使用Fn trait 更为常见,它的好处是允许闭包和函数

fn func(x: i64) -> bool {
    true
}
    
fn func_of_func(callback: impl FnOnce(i64) -> bool, arg: i64) -> bool {
    callback(arg)
}

fn main() {
    let is_positive = func;
    println!("{}", func_of_func(is_positive, 8));
    println!("{}", func_of_func(is_positive, 8));
}

fn(i64) -> bool已经是一个函数指针,所以&fn(i64) -> bool是一个函数指针的引用。 由于函数指针是Copy ,你永远不应该有任何理由写这个。

如果您正在编写一个将类似函数的东西作为参数的函数,您通常应该使用泛型(或impl Fn ,如Mike Graham 的回答,这意味着同样的事情):

fn func_of_func<F: FnOnce(i64) -> bool>(callback: F, arg: i64) -> bool {
    callback(arg)
}

这意味着当您使用func等函数项调用func_of_func时, callback将被编译为直接函数调用而不是函数指针,这样更易​​于编译器优化。

如果函数不能被泛型化(可能是因为它是一个对象安全特征的成员),你通常应该使用特征对象来代替,它允许调用者传递一个闭包:

fn func_of_func(callback: &dyn Fn(i64) -> bool, arg: i64) -> bool { ... }
fn func_of_func(callback: &mut dyn FnMut(i64) -> bool, arg: i64) -> bool { ... }
// using `FnOnce` requires boxing
fn func_of_func(callback: Box<dyn FnOnce(i64) -> bool>, arg: i64) -> bool { ... }

函数指针应该只在函数绝对不能捕获任何东西时使用。 它们主要用于 C 语言的 FFI,以及作为泛型结构中PhantomData类型参数。

参考

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM