本篇介紹 C++ 的 std::function 的用法教學,std::function
是 C++11 中加入的一個通用函數包裝器,它能夠將函數、函數物件(可調用物件)以及 Lambda 表達式等作為參數,儲存到一個物件中,並隨時調用這個函數。本文將說明 std::function
的基本用法及範例,詳情請繼續往下閱讀。
要使用 std::function 需要引入的標頭檔:<functional>
std::function 基本用法
以下是 std::function
的基本用法及範例,在這個範例中,我們首先定義了一個名為 add
的函數,它接受兩個整數參數並回傳它們的總和。然後我們使用 std::function
來定義了一個函數物件 func
,並將其初始化為指向 add
函數的指標。最後,我們通過函數物件 func
來調用 add
函數,傳遞兩個整數參數,並輸出它們的總和。
1 |
|
結果輸入如下,1
Sum: 7
使用 Lambda 表達式
在這個範例中,我們定義了一個匿名 Lambda 函數,它接受兩個整數參數並回傳它們的積。然後,我們使用 std::function
來定義了一個函數物件 func
,並將其初始化為這個 Lambda 函數。最後,我們通過函數物件 func
來調用 Lambda 函數,傳遞兩個整數參數,並輸出它們的相乘結果。
1 |
|
結果輸入如下,1
Product: 12
std::function 作為函數參數傳遞
在這個範例中,我們定義了一個名為 process
的函數,它接受一個 std::function
物件作為參數,以及兩個整數參數 a
和 b
。在 main
函數中,我們使用 Lambda 表達式來建立一個函數物件,並將其作為參數傳遞給 process
函數。在 process
函數內部,我們通過傳入的函數物件來執行相應的操作,並輸出結果。
1 |
|
結果輸入如下,1
Result: 3
std::function
提供了一個方便的方法來處理函數指標、函數物件和 Lambda 表達式,使得 C++ 中的函數操作更加靈活和方便。
在實務上也常用到 std::function 來做 callback 回調函式的的,詳細請見下範例,
用 std::function 取代傳統的 function pointer
讓我們先來看看一段使用傳統的 function pointer 的範例,1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18// g++ function-pointer-callback.cpp -o a.out
using namespace std;
void keyevent(int keycode, int status) {
cout << "keycode = " << keycode << " status = " << status << endl;
}
int main() {
void (*callback_keyevent)(int, int) = NULL;
callback_keyevent = keyevent;
if (callback_keyevent)
callback_keyevent(1, 0);
return 0;
}
改成 std::function 後變成這樣1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19// g++ std-function-callback.cpp -o a.out -std=c++11
using namespace std;
void keyevent(int keycode, int status) {
cout << "keycode = " << keycode << " status = " << status << endl;
}
int main() {
std::function<void(int, int)> callback_keyevent = nullptr;
callback_keyevent = keyevent;
if (callback_keyevent)
callback_keyevent(1, 0);
return 0;
}
使用 std::function
的優點
使用 std::function
取代傳統的函數指標(function pointer)有幾個優點:
可讀性佳:使用
std::function
可以使程式碼更易讀和理解。當你看到一個std::function
物件時,你立即知道它是一個函數物件,並且可以通過調用該物件來執行相應的操作。這比看到函數指標或其他較為抽象的函數表示形式更直觀。可接受 Lambda 函式:
std::function
可以輕鬆地接受 Lambda 表達式,這使得程式碼更加現代化和易於閱讀。Lambda 表達式通常用於定義簡單的、局部的函數行為,而std::function
的能力可以讓你將這些 Lambda 表達式作為函數物件使用,從而使程式碼更加簡潔和易於理解。更靈活的函數封裝:
std::function
可以封裝函數指標、函數物件、Lambda 表達式等,使得函數的使用更加靈活。這意味著你可以使用std::function
來處理更多類型的函數。更容易進行函數替換:由於
std::function
可以接受不同類型的函數物件,因此當你需要替換函數時,只需要將新的函數賦值給std::function
物件即可,而無需修改函數指標的類型。不受函數簽名限制:使用函數指標時,你必須確保函數指標的類型與所指向函數的簽名完全匹配。但是,使用
std::function
可以輕鬆地接受不同簽名的函數,從而提供了更大的彈性。提供了函數物件的拷貝和賦值能力:
std::function
物件可以被拷貝和賦值,這使得函數的傳遞和儲存更加方便。
總體來說,std::function
提供了一個更加現代化、靈活且安全的方法來處理函數,並且在許多場景下更加方便和易於使用。
以上就是 C++ std::function 用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!
其他參考
[1] std::function - cppreference.com
https://en.cppreference.com/w/cpp/utility/functional/function
[2] function::function - C++ Reference
http://www.cplusplus.com/reference/functional/function/function/
[3] C++11 std::function的用法 - 滴酱的个人空间 - OSCHINA
https://my.oschina.net/u/2274890/blog/499159
[4] C++11 std::function用法-码农场
https://www.hankcs.com/program/cpp/c11-std-function-usage.html
[5] Cocos2d-x 的 onKeyPressed 與 onKeyReleased
https://github.com/cocos2d/cocos2d-x/blob/e3438ed3fd10a304b7ca2cd3dad9b29fead818d2/cocos/base/CCEventListenerKeyboard.h
https://github.com/cocos2d/cocos2d-x/blob/e3438ed3fd10a304b7ca2cd3dad9b29fead818d2/cocos/base/CCEventListenerKeyboard.cpp
https://github.com/cocos2d/cocos2d-x/blob/e3438ed3fd10a304b7ca2cd3dad9b29fead818d2/tests/performance-tests/Classes/tests/PerformanceEventDispatcherTest.cpp
cocos2d-x 在 PerformanceEventDispatcherTest.cpp 的 KeyboardEventDispatchingPerfTest::generateTestFunctions 使用 onKeyPressed 接收一個 lambda 函式
[6] 邁向王者的旅途: 簡介 std::function (C++11 後的新功能)
https://shininglionking.blogspot.com/2017/01/stdfunction-c11.html
[7] Should I use std::function or a function pointer in C++? - Stack Overflow
https://stackoverflow.com/questions/25848690/should-i-use-stdfunction-or-a-function-pointer-in-c
這篇討論提到應該盡量使用 std::function 來取代 function pointer,除非有什麼其他特殊原因
[8] 在 C++ 裡傳遞、儲存函式 Part 3:Function Object in TR1 – Heresy’s Space
https://kheresy.wordpress.com/2010/11/12/function_object_tr1/
其它相關文章推薦
C/C++ 新手入門教學懶人包
std::thread 用法與範例
C++ std::sort 排序用法與範例完整介紹
std::queue 用法與範例
C++ virtual 的兩種用法
C/C++ 判斷檔案是否存在
C++ 設計模式 - 單例模式 Singleton Pattern
C/C++ call by value傳值, call by pointer傳址, call by reference傳參考 的差別