日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

c++11 std::bind与std::function

發(fā)布時間:2025/3/15 c/c++ 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c++11 std::bind与std::function 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.


function模板類和bind模板函數(shù),使用它們可以實(shí)現(xiàn)類似函數(shù)指針的功能,但卻比函數(shù)指針更加靈活,特別是函數(shù)指向類的非靜態(tài)成員函數(shù)時。

std::function可以綁定到全局函數(shù)/類靜態(tài)成員函數(shù)(類靜態(tài)成員函數(shù)與全局函數(shù)沒有區(qū)別),如果要綁定到類的非靜態(tài)成員函數(shù),則需要使用std::bind。

標(biāo)準(zhǔn)庫函數(shù)bind()和function()定義于頭文件<functional>中(該頭文件還包括許多其他函數(shù)對象),用于處理函數(shù)及函數(shù)參數(shù)。

std::bind綁定器

  • 將函數(shù)、成員函數(shù)和閉包轉(zhuǎn)成function函數(shù)對象
  • 將多元(n>1)函數(shù)轉(zhuǎn)成一元函數(shù)或者(n-1)元函數(shù)。

bind()接受一個函數(shù)(或者函數(shù)對象,或者任何你可以通過"(...)"符號調(diào)用的事物),生成一個其有某一個或多個函數(shù)參數(shù)被“綁定”或重新組織的函數(shù)對象。(譯注:顧名思義,bind()函數(shù)的意義就像它的函數(shù)名一樣,是用來綁定函數(shù)調(diào)用的某些參數(shù)的。)例如:

1 int f(int, char, double); 2 auto ff = bind(f, _1, 'c', 1.2); // 綁定f()函數(shù)調(diào)用的第二個和第三個參數(shù),返回一個新的函數(shù)對象為ff,它只帶有一個int類型的參數(shù) 3 int x = ff(7); // f(7, 'c', 1.2);

參數(shù)的綁定通常稱為"Currying"(譯注:Currying---“烹制咖喱燒菜”,此處意指對函數(shù)或函數(shù)對象進(jìn)行加工修飾操作), "_1"是一個占位符對象,用于表示當(dāng)函數(shù)f通過函數(shù)ff進(jìn)行調(diào)用時,函數(shù)ff的第一個參數(shù)在函數(shù)f的參數(shù)列表中的位置。第一個參數(shù)稱為"_1", 第二個參數(shù)為"_2",依此類推。例如:

1 int f(int, char, double); 2 auto frev = bind(f, _3, _2, _1); // 翻轉(zhuǎn)參數(shù)順序 3 int x = frev(1.2, 'c', 7); // f(7, 'c', 1.2);

? ? 此處,auto關(guān)鍵字節(jié)約了我們?nèi)ネ茢郻ind返回的結(jié)果類型的工作。
?? ?我們無法使用bind()綁定一個重載函數(shù)的參數(shù),我們必須顯式地指出需要綁定的重載函數(shù)的版本:

1 int g(int); 2 double g(double); 3 4 auto g1 = bind(g, _1); // 錯誤:調(diào)用哪一個g() ? 5 auto g2 = bind( (double(*)(double))g, _1); // 正確,但是相當(dāng)丑陋 1 void H(int a); 2 //綁定全局函數(shù) 3 auto f11 = std::bind(H, std::placeholders::_1); 4 auto的類型實(shí)際上是std::function<void(int)> 5 6 //綁定帶參數(shù)的成員函數(shù) 7 std::function<void (char*, int)> f = std::bind(&ReadHandler::ConnectPreProcess, this, std::placeholders::_1, std::placeholders::_1); 8 9 //三元函數(shù)轉(zhuǎn)換成一元函數(shù) 10 int f(int, char, double); 11 // 綁定f()函數(shù)調(diào)用的第二個和第三個參數(shù), 12 // 返回一個新的函數(shù)對象為ff,它只帶有一個int類型的參數(shù) 13 auto ff = bind(f, _1, ‘c’, 1.2); 14 int x = ff(7);

自己寫代碼示例如下:

int Func(int x, int y); auto bf1 = std::bind(Func, 10, std::placeholders::_1); bf1(20); ///< same as Func(10, 20) int HelloWorld::AddFunc( int a, int b ) {return a + b; }bool HelloWorld::init() {auto bf2 = std::bind(&HelloWorld::AddFunc,this , std::placeholders::_1, std::placeholders::_2 );auto result1 = bf2(10, 20); ///< same as a.Func(10, 20) std::function< int(int)> bf3 = std::bind(&HelloWorld::AddFunc, this, std::placeholders::_1, 100);auto result2 = bf3(10); ///< same as a.Func(10, 100) }

上面的例子中,bf1是把一個兩個參數(shù)普通函數(shù)的第一個參數(shù)綁定為10,生成了一個新的一個參數(shù)的可調(diào)用實(shí)體體; bf2是把一個類成員函數(shù)綁定了類對象,生成了一個像普通函數(shù)一樣的新的可調(diào)用實(shí)體; bf3是把類成員函數(shù)綁定了類對象和第二個參數(shù),生成了一個新的std::function對象。看懂了上面的例子,下面我們來說說使用bind需要注意的一些事項:

  • (1)bind預(yù)先綁定的參數(shù)需要傳具體的變量或值進(jìn)去,對于預(yù)先綁定的參數(shù),是pass-by-value的
  • (2)對于不事先綁定的參數(shù),需要傳std::placeholders進(jìn)去,從_1開始,依次遞增。placeholder是pass-by-reference的
  • (3)bind的返回值是可調(diào)用實(shí)體,可以直接賦給std::function對象
  • (4)對于綁定的指針、引用類型的參數(shù),使用者需要保證在可調(diào)用實(shí)體調(diào)用之前,這些參數(shù)是可用的
  • (5)類的this可以通過對象或者指針來綁定

std::function

它是函數(shù)、函數(shù)對象、函數(shù)指針、和成員函數(shù)的包裝器,可以容納任何類型的函數(shù)對象,函數(shù)指針,引用函數(shù),成員函數(shù)的指針。
以統(tǒng)一的方式處理函數(shù)、函數(shù)對象、函數(shù)指針、和成員函數(shù)。允許保存和延遲執(zhí)行函數(shù)。

  • 函數(shù)和成員函數(shù)作為function

function是一個擁有任何可以以"(...)"符號進(jìn)行調(diào)用的值的類型。特別地,bind的返回結(jié)果可以賦值給function類型。function十分易于使用。(譯注:更直觀地,可以把function看成是一種表示函數(shù)的數(shù)據(jù)類型,就像函數(shù)對象一樣。只不過普通的數(shù)據(jù)類型表示的是數(shù)據(jù),function表示的是函數(shù)這個抽象概念。)例如:

1 typedef std::function<float (int x, int y)> f ;// 構(gòu)造一個函數(shù)對象,它能表示的是一個返回值為float,兩個參數(shù)為int,int的函數(shù) 2 struct int_div { // 構(gòu)造一個可以使用"()"進(jìn)行調(diào)用的函數(shù)對象類型 3 float operator() (int x, int y) const { return ((float)x)/y; }; 4 }; 5 6 void HelloWorld::testing() 7 { 8 f f1= int_div(); // 賦值 9 auto result3 = f1( 10, 2); 10 }

成員函數(shù)可被看做是帶有額外參數(shù)的自由函數(shù):

1 struct int_div { // 構(gòu)造一個可以使用"()"進(jìn)行調(diào)用的函數(shù)對象類型 2 float operator() (int x, int y) const { return ((float)x)/y; }; 3 int int_div_fun( int x ){ return x; }; 4 }; 5 typedef std::function<int (int_div*, int)> f_2; 6 7 bool HelloWorld::init() 8 { 9 f_2 f2 = std::mem_fn(&int_div::int_div_fun); // 指向成員函數(shù) 10 11 int_div int_div_object; 12 int v = f2(&int_div_object, 5); // 在對象x上用參數(shù)5調(diào)用X::foo() 13 std::function<int (int)> ff = std::bind( f2, &int_div_object, std::placeholders::_1); // f的第一個參數(shù)是&x 14 v = ff(5); // 調(diào)用x.foo(5) 15 16 17 }

ps:被vs2012的bug給坑了。因為看網(wǎng)上的代碼于是剛開始第9行是這么寫的:f_2 f2 = &int_div::int_div_fun;?

然后就報錯誤:Error 1 error C2664: 'std::_Func_class<_Ret,_V0_t,_V1_t>::_Set' : cannot convert parameter 1 from '_Myimpl *' to 'std::_Func_base<_Rx,_V0_t,_V1_t> *'

查了一下,vs2010沒有這個編譯錯誤,但是2012有。2012必須得加上std::mem_fn才能編譯。

  • 可以用function取代函數(shù)指針。因為它可以保存函數(shù)延遲執(zhí)行,所以比較適合作為回調(diào)函數(shù),也可以把它看做類似于c#中特殊的委托,只有一個成員的委托。
  • 1 struct int_div { // 構(gòu)造一個可以使用"()"進(jìn)行調(diào)用的函數(shù)對象類型 2 float operator() (int x, int y) const { return ((float)x)/y; }; 3 int int_div_fun( int x ){ return x; }; 4 5 int_div( std::function<void()>& f ):m_callback(f){}; 6 void Notify() 7 { 8 m_callback(); 9 } 10 std::function<void()> m_callback; 11 };
  • function還可以作為函數(shù)入?yún)?#xff0c;這樣可以在函數(shù)外部控制函數(shù)的內(nèi)部行為了,讓我們的函數(shù)變得更加靈活。
  • void Foo(int x, std::function<void(int)>& f) { if(x%2==0) f(x); }void G(int x) { cout<<x<<endl; }void H(int x) { cout<<x+2<<endl; }void TestFoo() { auto f = std::bind(G, std::placeholders::_1); Foo(4, f);//在Foo函數(shù)外面更改f的行為 f = std::bind(H, std::placeholders::_1); Foo(4, f); }

c++11中推出function是為了泛化函數(shù)對象,函數(shù)指針,引用函數(shù),成員函數(shù)的指針,讓我們可以按更統(tǒng)一的方式寫出更加泛化的代碼;推出bind是為了替換和增強(qiáng)之前標(biāo)準(zhǔn)庫的bind1st和bind2st,讓我們的用起來更方便!

新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產(chǎn)品紅包拿不停!

總結(jié)

以上是生活随笔為你收集整理的c++11 std::bind与std::function的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。