簡體   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