一個典型的單線程伺服器示例如下: while (true) { Socket socket = null; try { // 接收客戶連接 socket = serverSocket.accept(); // 從socket中獲得輸入流與輸出流,與客戶通信 ... } catch(IOExcepti ...
什麼是函數指針
通過函數指針允許我們使用函數作為另一個函數的參數。函數的類型是 fn (使用小寫的 ”f” )以免與 Fn 閉包 trait 相混淆。fn 被稱為 函數指針(function pointer)。指定參數為函數指針的語法類似於閉包。
函數指針類型(使用關鍵字 fn
寫出)指向那些在編譯時不必知道函數標識符的函數。它們也可以由函數項類型或非捕獲(non-capturing)閉包經過一次自動強轉(coercion)來創建
如何在Rust中定義和使用函數指針
下麵是一個簡單的代碼示例,它演示瞭如何在Rust中定義和使用函數指針:
fn add_one(x: i32) -> i32 {
x + 1
}
fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
f(arg) + f(arg)
}
fn main() {
let answer = do_twice(add_one, 5);
println!("The answer is: {}", answer);
}
複製代碼
這會列印出 The answer is: 12。do_twice 中的 f 被指定為一個接受一個 i32 參數並返回 i32 的 fn。接著就 可以在 do_twice 函數體中調用 f。在 main 中,可以將函數名 add_one 作為第一個參數傳遞給 do_twice。
函數指針與閉包的區別
函數指針和閉包都可以用來表示可調用對象,但它們之間有一些重要的區別。其中一個區別是,閉包可以捕獲其周圍環境中的變數,而函數指針則不能。
不同於閉包,fn 是一個類型而不是一個 trait,所以直接指定 fn 作為參數而不是聲明一個帶有 Fn 作為 trait bound 的泛型參數。
函數指針實現了所有三個閉包 trait(Fn、FnMut 和 FnOnce),所以總是可以在調用期望閉包的函數時 傳遞函數指針作為參數。
傾向於編寫使用泛型和閉包 trait 的函數,這樣它就能接受函數或閉包作為參數。 一個只期望接受 fn 而不接受閉包的情況的例子是與不存在閉包的外部代碼交互時:C 語言的函數可以接受函數作為參數,但 C 語言沒有閉包。
函數指針的應用場景
-
可以作為參數傳遞給其他函數,以便在函數內部調用。這在一些高階函數(higher-order functions)中非常常見,例如
map
和filter
等。 -
函數指針還可以用於定義回調函數(callback functions),例如在事件驅動編程(event-driven programming)中。
-
函數指針還可以存儲在數據結構中,以便稍後調用。這在一些演算法中非常有用,例如排序演算法。
函數指針的優缺點
函數指針的優點之一是它們沒有運行時開銷。這意味著它們可以在不影響性能的情況下用於表示可調用對象。
但是,函數指針也有一些局限性。例如,它們不能捕獲其周圍環境中的變數,這使得它們不如閉包靈活。此外,函數指針只能指向那些在編譯時已知的函數,這意味著它們不能用於表示匿名函數。from劉金,轉載請註明原文鏈接。感謝!