當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Rust fn用法及代碼示例


本文簡要介紹rust語言中 Primitive Type fn 的用法。

函數指針,例如 fn(usize) -> bool

另請參閱特征 Fn FnMut FnOnce

函數指針是指向的指針代碼,不是數據。它們可以像函數一樣被調用。與引用一樣,函數指針除其他外被假定不為空,因此如果您想通過 FFI 傳遞函數指針並能夠容納空指針,請使您的類型Option<fn()>以及您所需的簽名。

安全性

普通函數指針是通過強製轉換普通函數或不捕獲環境的閉包來獲得的:

fn add_one(x: usize) -> usize {
    x + 1
}

let ptr: fn(usize) -> usize = add_one;
assert_eq!(ptr(5), 6);

let clos: fn(usize) -> usize = |x| x + 5;
assert_eq!(clos(5), 10);

除了根據簽名而變化之外,函數指針還有兩種類型:安全和不安全。普通fn()函數指針隻能指向安全函數,而unsafe fn()函數指針可以指向安全或不安全函數。

fn add_one(x: usize) -> usize {
    x + 1
}

unsafe fn add_one_unsafely(x: usize) -> usize {
    x + 1
}

let safe_ptr: fn(usize) -> usize = add_one;

//ERROR: mismatched types: expected normal fn, found unsafe fn
//let bad_ptr: fn(usize) -> usize = add_one_unsafely;

let unsafe_ptr: unsafe fn(usize) -> usize = add_one_unsafely;
let really_safe_ptr: unsafe fn(usize) -> usize = add_one;

ABI

最重要的是,函數指針可能會根據它們使用的 ABI 而有所不同。這是通過在類型前添加 extern 關鍵字,然後是相關 ABI 來實現的。默認 ABI 為 “Rust”,即 fn()extern "Rust" fn() 的類型完全相同。指向具有 C ABI 的函數的指針將具有類型 extern "C" fn()

extern "ABI" { ... } 塊使用 ABI “ABI” 聲明函數。此處的默認值為“C”,即在extern {...} 塊中聲明的函數具有“C” ABI。

有關詳細信息和支持的 ABI 列表,請參閱nomicon 關於外國調用約定的部分.

可變函數

帶有 “C” 或 “cdecl” ABI 的外部函數聲明也可以可變參數,允許使用可變數量的參數來調用它們。正常的 Rust 函數,即使是那些帶有extern "ABI", 不能是可變的。有關詳細信息,請參閱nomicon 關於可變參數函數的部分.

創建函數指針

什麽時候bar是函數名,然後是表達式bar不是函數指針。相反,它表示唯一標識該函數的不可命名類型的值bar。該值的大小為零,因為類型已經標識了該函數。這樣做的優點是 “calling” 值(它實現了Fn*特征)不需要動態調度。

這種大小為零的類型強製轉換為常規函數指針。例如:

use std::mem;

fn bar(x: i32) {}

let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar`
assert_eq!(mem::size_of_val(&not_bar_ptr), 0);

let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer
assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());

let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar`

最後一行顯示&bar 也不是函數指針。相反,它是對function-specific ZST 的引用。當bar 是一個函數時,&bar 本質上永遠不是你想要的。

特性

函數指針實現以下特征:

由於 Rust 類型係統的臨時限製,這些特征僅在具有 12 個或更少參數的函數上實現,帶有 "Rust""C" ABI。將來,這種情況可能會改變。

另外,函數指針任何簽名、ABI 或安全性std::marker::Copy, 和所有安全的函數指針實現std::ops::Fn,std::ops::FnMut, 和std::ops::FnOnce。這是可行的,因為這些特征是編譯器特別已知的。

相關用法


注:本文由純淨天空篩選整理自rust-lang.org大神的英文原創作品 Primitive Type fn。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。