本篇介紹 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> #include <functional> int add (int a, int b) { return a + b; } int main () { std ::function<int (int , int )> func = add; std ::cout << "Sum: " << func(3 , 4 ) << std ::endl ; return 0 ; }
結果輸入如下,
使用 Lambda 表達式 在這個範例中,我們定義了一個匿名 Lambda 函數,它接受兩個整數參數並回傳它們的積。然後,我們使用 std::function
來定義了一個函數物件 func
,並將其初始化為這個 Lambda 函數。最後,我們通過函數物件 func
來調用 Lambda 函數,傳遞兩個整數參數,並輸出它們的相乘結果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <iostream> #include <functional> int main () { std ::function<int (int , int )> func = [](int a, int b) { return a * b; }; std ::cout << "Product: " << func(3 , 4 ) << std ::endl ; return 0 ; }
結果輸入如下,
std::function 作為函數參數傳遞 在這個範例中,我們定義了一個名為 process
的函數,它接受一個 std::function
物件作為參數,以及兩個整數參數 a
和 b
。在 main
函數中,我們使用 Lambda 表達式來建立一個函數物件,並將其作為參數傳遞給 process
函數。在 process
函數內部,我們通過傳入的函數物件來執行相應的操作,並輸出結果。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include <iostream> #include <functional> void process (std ::function<int (int , int )> func, int a, int b) { std ::cout << "Result: " << func(a, b) << std ::endl ; } int main () { process([](int a, int b) { return a / b; }, 6 , 2 ); return 0 ; }
結果輸入如下,
std::function
提供了一個方便的方法來處理函數指標、函數物件和 Lambda 表達式,使得 C++ 中的函數操作更加靈活和方便。
在實務上也常用到 std::function 來做 callback 回調函式的的,詳細請見下範例,
用 std::function 取代傳統的 function pointer 讓我們先來看看一段使用傳統的 function pointer 的範例,function-pointer-callback.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> #include <string> 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 後變成這樣std-function-callback.cpp 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 #include <iostream> #include <string> #include <functional> 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.comhttps://en.cppreference.com/w/cpp/utility/functional/function [2] function::function - C++ Referencehttp://www.cplusplus.com/reference/functional/function/function/ [3] C++11 std::function的用法 - 滴酱的个人空间 - OSCHINAhttps://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 與 onKeyReleasedhttps://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 Overflowhttps://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 Spacehttps://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傳參考 的差別