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
注意事項:
- 關於可調用實體轉換爲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可以通過對象或者指針來綁定