c++11 std::function && std::bind

1.function

        std::function 對象是對C++中現有的可調用實體的一種類型安全的包裹(函數指針這類可調用實體,是類型不安全的)。可調用實體主要包括:

  • 函數(全局函數, 靜態函數)
  • 函數指針
  • 函數引用
  • 隱式轉換爲函數指定的對象

實例:普通函數仿函數的例子

#include <functional>

std::function< size_t (const char*)> PrintFunc;

//正常的函數 -> std::function object
//打印函數
size_t cprint(const char* .......)
{
   printf(".........");
}

PrintFunc = cprint;
PrintFunc("Hello world");
打印結果: hello world

----------------------------------------------------
//functor(仿函數)--> std::function object
class cprint
{
public:
   size_t operator()(const char*){.....}
};

cprint  object;
PrintFunc = object
PrintFunc("hello world");
打印結果: hello world


注意事項:

  1. 關於可調用實體轉換爲std::function對象需要遵守以下兩條原則:

        a.轉換後的std::function對象的參數能轉換爲可調用實體的參數

        b.可高用實體的返回值能轉換爲std::function對象的(所有的可調用實體的返回值都與返回void的std::function對象的返回值兼容)

     2.std::function對象可以refer to 滿足(1)中條件的任意可調用實體

     3.std::function object最大的用處就是在實現函數回調,使用者需要注意,不能被用來檢查相等或者不相等

補充知識仿函數(functor):就是使一個類的使用看上去像一個函數,其實現就是類中實現一個operator(),這個類就有了類似函數的行爲,就是一個仿函數。

//less的定義
 
template<typename _Tp>
    struct less : public binary_function<_Tp, _Tp, bool>
    {
      bool
      operator()(const _Tp& __x, const _Tp& __y) const
      { return __x < __y; }
    };

//set的定義
template<typename _Key, typename _Compare = std::less<_Key>,
       typename _Alloc = std::allocator<_Key> >
    class set;

 

2.std::bind

2.1 std::bind1st 和 std::bind2nd

        bind是這樣一種機制,它可以預先把指定可調用實體的某些參數綁定到已有變量,產生一個新的可調用實體,這種機制在回調函數的使用過程中頗爲有用。c++98中,有兩個函數bind1st和bind2st,他們分別用來綁定functor的第一個和第二個參數,他們都是只可以綁定一個參數。

例子:

#include <iostream>
#include <functional>
#include <algorithm>
#include <vector>
using namespace std;

int main()
{
    vector<int> coll;
    for (int i = 1; i <= 10; ++i)
    {
        coll.push_back(i);
    }

    // 查找元素值大於10的元素的個數
    // 也就是使得10 < elem成立的元素個數 
    // 意義:   從vector中找出大於10的數,  判斷方法   less-->   a   <  b
    //其中, a固定爲10, coll.begin() < b < coll.end()
    int res = count_if(coll.begin(), coll.end(), bind1st(less<int>(), 10));
    cout << res << endl;

    // 查找元素值小於10的元素的個數
    // 也就是使得elem < 10成立的元素個數 
    res = count_if(coll.begin(), coll.end(), bind2nd(less<int>(), 10));
    cout << res << endl;

    return 0;
}

解釋:1. less<int>()其實是一個函數, 如果沒有std::bind1st和std::bind2nd,使用less<int>,代碼如下:

less<int> functor = less<int>();
bool bRet = functor(9, 20); // 返回true

less<int>()函數對象需要二個參數,比如上面 9 < 20進行比對, 其中9叫做 left參數,20叫做right參數

  • 當使用std::bind1st的時候,就表示綁定left參數,left參數不變,而right參數就是對應容器中的element.
  • 當使用std::bind2nd的時候,就表示綁定right參數,right參數不變,而left參數就是對應容器中的element.

2.2定義

  std::function綁定全局函數, 靜態函數,std::bind綁定類的成員函數

不借助std::bind, 傳*this變量的例子:

#include <iostream>
#include <functional>
using namespace std;

class View
{
public:
    void onClick(int x, int y)
    {
        cout << "X : " << x << ", Y : " << y << endl;
    }
};

// 定義function類型, 三個參數
function<void(View, int, int)> clickCallback;

int main(int argc, const char * argv[])
{
    View button;

    // 指向成員函數
    clickCallback = &View::onClick;

    // 進行調用
    clickCallback(button, 10, 123);
    return 0;
}

使用std::bind的例子​​​​​​​

#include <iostream>
#include <functional>
using namespace std;

int TestFunc(int a, char c, float f)
{
    cout << a << endl;
    cout << c << endl;
    cout << f << endl;

    return a;
}

int main()
{
    auto bindFunc1 = bind(TestFunc, std::placeholders::_1, 'A', 100.1);
    bindFunc1(10);

    cout << "=================================\n";

    auto bindFunc2 = bind(TestFunc, std::placeholders::_2, std::placeholders::_1, 100.1);
    bindFunc2('B', 10);

    cout << "=================================\n";
    

    auto bindFunc3 = bind(TestFunc, std::placeholders::_2, std::placeholders::_3, std::placeholders::_1);
    bindFunc3(100.1, 30, 'c');

  //打印:  30, C , 100.1

    return 0;
}

上面的例子中,比如bindFunc3函數中:表示binFunc3中的第2個參數對應TestFunc中的第一個參數。bindFunc3中的第3個參數對應TestFunc中的第二個參數,bindFunc3中的第1個參數對應TestFunc中的第三個參數。

       

使用std::bind需要注意的地方:

  • bind預先綁定的參數需要傳具體的變量或值進去,對於預先綁定的參數,是pass-by-value的。
  • 對於不事先綁定的參數,需要傳std::placeholders進去,從_1開始,依次遞增。placeholder是pass-by-reference的
  • bind的返回值是可調用實體,可以直接賦給std::function對象。
  • 對於綁定的指針,引用類型的參數,使用者需要保證在可調用實體之前,這些參數是可用的。
  • ​​​​​​​類的this可以通過對象或者指針來綁定

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章