(原創)C++11改進我們的程序之簡化我們的程序(五)


這次要講的是:c++11中的bind和function

std::function

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

  • 函數和成員函數作為function
void G();
struct A
{
void H(){}
};

std::function<void()> f = G; //全局函數

A a;
std::function<void()> f 1= std::bind(&A::H, a); //成員函數
  • 可以用function取代函數指針。因為它可以保存函數延遲執行,所以比較適合作為回調函數,也可以把它看做類似於c#中特殊的委托,只有一個成員的委托。
struct A
{
A(std::function<void()>& f):m_callback(f)
void Notify()
{
m_callback();//回調到上層
}

std::function<void()> m_callback;
}
  • function還可以作為函數入參,這樣可以在函數外部控制函數的內部行為了,讓我們的函數變得更加靈活。
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函數外面更改f的行為
f = std::bind(H, std::placeholders::_1);
Foo(4, f);
}

std::bind綁定器

  • 將函數、成員函數和閉包轉成function函數對象
  • 將多元(n>1)函數轉成一元函數或者(n-1)元函數。
void H(int a);
//綁定全局函數
auto f11 = std::bind(H, std::placeholders::_1);
auto的類型實際上是std::function<void(int)>

//綁定帶參數的成員函數
std::function<void (char*, int)> f = std::bind(&ReadHandler::ConnectPreProcess, this, std::placeholders::_1, std::placeholders::_1);

//三元函數轉換成一元函數
int f(int, char, double);
// 綁定f()函數調用的第二個和第三個參數,
// 返回一個新的函數對象為ff,它只帶有一個int類型的參數
auto ff = bind(f, _1, ‘c’, 1.2);    
int x = ff(7); 
  • bind簡化和增強bind1st和bind2nd

  其實bind簡化和增強了之前標准庫中bind1st和bind2nd,它完全可以替代bind1s和bind2st,並且能組合函數。我們知道bind1st和bind2nd將一個二元算子轉換成一個一元算子。

//查找元素值大於10的元素的個數
int count = count_if(coll.begin(), coll.end(), std::bind1st(less<int>(), 10));
//查找元素之小於10的元素
int count = count_if(coll.begin(), coll.end(), std::bind2nd(less<int>(), 10));

  本質上是對一個二元函數less<int>的調用,但是它卻要分別用bind1st和bind2nd,而且還要想想到底是用bind1st還是bind2nd,用起來感覺不方便。現在用bind,就可以以統一的方式去實現了。

//查找元素值大於10的元素的個數
int count = count_if(coll.begin(), coll.end(), bind(less<int>(), 10, _1));
//查找元素之小於10的元素
int count = count_if(coll.begin(), coll.end(), bind(less<int>(), _1, 10));
這樣我就不用關心到底是用bind1st還是bind2nd了,只要用bind就都搞定了。
  • bind函數組合

bind的還有一個強大之處就是函數組合。假設我們要找出集合中大於5小於10的元素個數怎么做呢?我們需要一個邏輯與才能做到類似於:

std::bind(std::logical_and<bool>(),_1,_2);

然后,我們需要另一個謂詞來回答 _1 是否大於5。

std::bind(std::greater<int>(),_1,5);

然后,我們還需要另一個謂詞來回答 _1 是否小於等於10。

std::bind(std::less_equal<int>(),_1,10);

最后,我們需要把它們兩個用邏輯與合起來,就象這樣:

//查找集合中大於5小於10的元素個數
auto f = bind(std::logical_and<bool>(), bind(std::greater<int>(),_1,5), bind(std::less_equal<int>(),_1,10));
int count = count_if(coll.begin(), coll.end(), f);

  c++11中推出function是為了泛化函數對象,函數指針,引用函數,成員函數的指針,讓我們可以按更統一的方式寫出更加泛化的代碼;推出bind是為了替換和增強之前標准庫的bind1st和bind2st,讓我們的用起來更方便!

c++11 boost技術交流群:296561497,歡迎大家來交流技術。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM