C++11 std::function和std::bind 的使用示例詳解
概述
C++11中的
std::function
和std::bind
是函數(shù)對象的重要組成部分,它們可以用于將函數(shù)和參數(shù)綁定在一起,形成一個可調用的對象。std::function
可以存儲任意可調用對象,包括函數(shù)指針、函數(shù)對象、lambda表達式等,而std::bind
則可以將函數(shù)和參數(shù)綁定在一起,形成一個新的可調用對象。它們的使用可以大大簡化代碼,提高代碼的可讀性和可維護性。
可調用對象
C++中有如下幾種可調用對象,
函數(shù)、函數(shù)指針、lambda表達式、bind對象、函數(shù)對象
。
其中,lambda表達式和bind對象是C++11標準中提出的(bind機制并不是新標準中首次提出,而是對舊版本中bind1st和bind2st的合并)。
std::function
std::function是一個可調用對象包裝器,是一個類模板,可以容納除了類成員函數(shù)指針之外的所有可調用對象,它可以用統(tǒng)一的方式處理函數(shù)、函數(shù)對象、函數(shù)指針,并允許保存和延遲它們的執(zhí)行。
使用std::function可以實現(xiàn)回調函數(shù)、事件處理等功能。
std::function函數(shù)原型
#include <functional> template<class R, class... Args> class function<R(Args...)>; //其中,R 表示返回值類型,Args... 表示參數(shù)類型列表。 //例如,function<int(float, double)> 表示一個返回值為 int,接受一個 float 和一個 double 類型參數(shù)的函數(shù)對象。
std::function的主要作用
- 對C++中各種可調用實體(普通函數(shù)、Lambda表達式、函數(shù)指針、以及其它函數(shù)對象等)的封裝,形成一個新的可調用的std::function對象,簡化調用;
- 對C++中現(xiàn)有的可調用實體的一種類型安全的包裹(如:函數(shù)指針這類可調用實體,是類型不安全的)。
- 將函數(shù)作為參數(shù)傳遞給其他函數(shù);
- 將函數(shù)作為返回值返回;
- 將函數(shù)對象作為參數(shù)傳遞給其他函數(shù);
- 將函數(shù)對象作為返回值返回。
//例如,定義一個返回值為int,參數(shù)為兩個int的函數(shù)對象: std::function<int(int, int)>func; //可以將一個函數(shù)指針或lambda表達式賦值給函數(shù)對象: int add(int a, int b) { return a +b; } func = add; // 函數(shù)指針賦值 func = [](int a, int b) { return a + b; };// lambda表達式賦值 //調用函數(shù)對象可以使用operator(),例如: int result = func(1, 2); // 調用add函數(shù),返回3
std::function的優(yōu)缺點
- 優(yōu)點:
可以方便地實現(xiàn)回調函數(shù)、事件處理等功能,同時也可以用于實現(xiàn)函數(shù)對象的封裝和傳遞。
- 缺點:
它的使用會帶來一定的性能開銷,因為它需要在運行時進行類型檢查和動態(tài)分配內存。
此外,如果使用不當,也容易引起內存泄漏和對象生命周期管理的問題。
std::bind
std::function是一個可調用對象包裝器,是一個類模板,可以容納除了類成員函數(shù)指針之外的所有可調用對象,它可以用統(tǒng)一的方式處理函數(shù)、函數(shù)對象、函數(shù)指針,并允許保存和延遲它們的執(zhí)行。
std::bind函數(shù)原型
template<class F, class... Args> /unspecified/ bind(F&& f, Args&&... args); //其中,F(xiàn)是要綁定的函數(shù)對象,Args是要綁定的參數(shù)。返回值是一個新的可調用對象,可以直接調用或者存儲起來后再調用。
std::bind的主要作用
- 將可調用對象和其參數(shù)綁定成一個仿函數(shù);
- 只綁定部分參數(shù),減少可調用對象傳入的參數(shù)。
- 綁定函數(shù)對象的參數(shù),生成一個新的可調用對象,可以方便地將函數(shù)對象作為參數(shù)傳遞給其它函數(shù)。
- 可以將成員函數(shù)綁定到對象上,生成一個新的可調用對象,方便地調用成員函數(shù)。
- 可以將成員函數(shù)綁定到對象指針上,生成一個新的可調用對象,方便地調用成員函數(shù)。
- 可以將成員函數(shù)綁定到對象引用上,生成一個新的可調用對象,方便地調用成員函數(shù)。
- 可以將函數(shù)對象綁定到函數(shù)指針上,生成一個新的可調用對象,方便地調用函數(shù)對象。
- 可以將函數(shù)對象綁定到函數(shù)引用上,生成一個新的可調用對象,方便地調用函數(shù)對象。
- 可以將函數(shù)對象綁定到std::function對象上,生成一個新的可調用對象,方便地調用函數(shù)對象。
例如,我們有一個函數(shù)對象:void foo(int a, int b, int c) { std::cout << a << " " << b << " " << c << std::endl; }
我們可以使用std::bind將它綁定到一些參數(shù)上:auto f = std::bind(foo, 1, 2, 3);
這里,f是一個新的可調用對象,它綁定了foo函數(shù)和參數(shù)1、2、3。我們可以像調用原始函數(shù)對象一樣調用它:f(); // 輸出:1 2 3
我們也可以只綁定部分參數(shù):auto g = std::bind(foo, 1, std::placeholders::_1, 3);
這里,std::placeholders::_1表示占位符,它表示在調用g時,第二個參數(shù)會被傳遞給foo函數(shù)。我們可以這樣調用g:g(2); // 輸出:1 2 3
這就是std::bind的基本用法。它可以方便地將函數(shù)對象和參數(shù)綁定在一起,生成一個新的可調用對象。
std::bind的優(yōu)缺點
優(yōu)點:
可以方便地實現(xiàn)函數(shù)對象的復用和參數(shù)的延遲綁定,從而提高代碼的可讀性和可維護性。
缺點:
可能會導致代碼的復雜性增加,特別是當參數(shù)較多時,需要謹慎使用。
代碼示例
#pragma once #include <iostream> #include <functional> class A { public: bool TESTA(int, char*, int) { /* implementation */ } }; class B { public: bool TESTB(std::function<bool(int, char*, int)> func) { /* implementation */ } }; int main() { A objA; B objB; auto lambda = [](int a, char* b, int c) { /* implementation */ }; objB.TESTB(lambda); objB.TESTB(std::bind(&A::TESTA, &objA, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); return 0; }
總結
- 預綁定的參數(shù)是以值傳遞的形式,不預綁定的參數(shù)要用std::placeholders(占位符)的形式占位,從_1開始,依次遞增,是以引用傳遞的形式;
- std::placeholders表示新的可調用對象的第幾個參數(shù),而且與原函數(shù)的該占位符所在位置的進行匹配;
- bind綁定類成員函數(shù)時,第一個參數(shù)表示對象的成員函數(shù)的指針,第二個參數(shù)表示對象的地址,這是因為對象的成員函數(shù)需要有this指針。并且編譯器不會將對象的成員函數(shù)隱式轉換成函數(shù)指針,需要通過&手動轉換;
- std::bind的返回值是可調用實體,可以直接賦給std::function。
到此這篇關于C++11 std::function和std::bind 的使用的文章就介紹到這了,更多相關C++11 std::function和std::bind內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
C語言數(shù)據(jù)結構之二叉鏈表創(chuàng)建二叉樹
這篇文章主要介紹了C語言數(shù)據(jù)結構之?二叉鏈表創(chuàng)建二叉樹,下文我們?yōu)榱烁奖愕氖褂枚鏄浣Y構體,可以使用?typedef?對結構體進行命名,具體內容需要的小伙伴可以參考一下2022-02-02