标签:
一.std::function
C++中的可调用对象虽然具有比较统一操作形式(除了类成员指针之外,都是后面加括号进行调用),但定义方法五花八门。为了统一泛化函数对象,函数指针,引用函数,成员函数的指针的各种操作,让我们可以按更统一的方式写出更加泛化的代码,C++11推出了std::function。
std::function是可调用对象的包装器。它是一个类模板,可以容纳除了类成员(函数)指针之外的所有可调用对象。通过指定它的模板参数,它可以用统一的方式处理函数,函数对象,函数指针,并允许保存和延迟执行它们。
1 #include <iostream> 2 #include <functional> 3 4 using namespace std; 5 6 void func(void){ 7 cout << __FUNCTION__ << "(" << a << ") ->: "; 8 } 9 10 class Foo 11 { 12 public: 13 static int foo_func(int a){ 14 cout << __FUNCTION__ << "(" << a << ") ->: "; 15 return a; 16 } 17 }; 18 19 class bar 20 { 21 public: 22 int operator()(int a){ 23 cout << __FUNCTION << "(" << a << ") ->: "; 24 return a; 25 } 26 }; 27 28 int main(){ 29 //绑定一个普通函数 30 std::function<void(void)> fry = func; 31 fr1(); 32 33 34 //绑定一个类的静态成员函数 35 std::function<int(int)> fr2 = Foo::foo_func; 36 cout << fr2(123) << endl; 37 38 //绑定一个仿函数 39 Bar bar; 40 fr2 = bar; 41 cout << fr2(123) <<endl; 42 43 return 0; 44 }
std::function的使用方法:我们给std::function填入合适的函数签名(即一个函数类型,只需要包括返回值和参数表)之后,它就变成了一个可以容纳所有这一类调用方式的“函数包装器”。
1 #include <iostream> 2 #include <functional> 3 4 using namespace std; 5 6 class A 7 { 8 public: 9 A(const std::function<void()>& f){ 10 :callback_(f){} 11 12 void notify(void){ 13 callback_(); 14 } 15 private: 16 std::function<void()> callback_; 17 }; 18 19 class Foo 20 { 21 public: 22 void operator()(void){ 23 cout << __FUNCTION__<< endl; 24 } 25 }; 26 27 int main(){ 28 Foo foo; 29 A aa(foo); 30 aa.notify(); 31 32 return 0; 33 }
从上面的例子看,std::function可以取代函数指针的作用。因为它可以保存函数延迟执行,所以比较适合作为回调函数,也可以把它看做类似于C#中特殊的委托(只有一个成员的委托)。
1 #include <iostream> 2 #include <functional> 3 4 using namespace std; 5 6 void call_when_even(int x, const std::function<void(int)>& f){ 7 if(!(x & 1)){ 8 f(x); 9 } 10 } 11 12 void output(int x){ 13 cout << x <<" "; 14 } 15 16 int main(void){ 17 for(int i=0;i<10;i++){ 18 call_when_even(i, output); 19 } 20 cout<<endl; 21 22 return 0; 23 }
std::function还可以作为函数入参,这样可以在函数外部控制函数的内部行为了,让我们的函数变得更加灵活。
二.std::bind绑定器
std::bind用来将可调用对象与其参数一起进行绑定。绑定后的结果可以使用std::function进行保存,并延迟调用到任何我们需要的时候。通俗来讲,它主要有两大作用:
1).将可调用对象与其参数一起绑定成一个仿函数。
2).将多元(参数个数为n,n>1)可调用对象转成一元或者(n-1)元可调用对象,即只绑定部分参数。
function模板类和bind模板函数,都可以实现类似函数指针的功能,但却却比函数指针更加灵活,特别是函数指向类的非静态成员函数时。
1).std::function可以绑定到全局函数/类静态成员函数(类静态成员函数与全局函数没有区别)。
2).绑定到类的非静态成员函数,则需要使用std::bind。
1 #include <iostream> 2 #include <functional> 3 4 using namespace std; 5 6 void call_when_even(int x, const std::function<void(int)>& f){ 7 if(!(x & 1)){ 8 f(x); 9 } 10 } 11 12 void output(int x){ 13 cout << x << " "; 14 } 15 16 void output_add_2(int x){ 17 cout << x +2 << " "; 18 } 19 20 int main(){ 21 { 22 auto fr = std::bind(output, std::placeholders::_1); 23 for(int i=0;i<10;i++){ 24 call_when_even(i, fr); 25 } 26 cout << endl; 27 } 28 29 { 30 auto fr = std::bind(output_add_2, std::placeholders::_1); 31 for(int i=0;i<10;i++){ 32 call_when_even(i, fr); 33 } 34 cout << endl; 35 } 36 37 return 0; 38 }
"std::placeholders::_1"是一个占位符对象,用于表示当函数output(output_add_2)通过函数fr进行调用时,函数fr的第一个参数在函数output(output_add_2)的参数列表中的位置。
下面是两个样例:
1 #include <iostream> 2 #include <functional> 3 4 using namespace std; 5 6 class A 7 { 8 public: 9 int i_=0; 10 11 void output(int x, int y){ 12 cout << x << " " << y <<endl; 13 } 14 }; 15 16 int main(){ 17 A a; 18 std::function<void(int, int)> fr = std::bind(&A::output, &a, std::placeholders::_1,std::placeholders::_2); 19 fr(1,2); 20 21 std::function<int&(void)> fr_i = std::bind(&A::i_, &a); 22 fr_i() = 123; 23 cout << a.i_ << endl; 24 25 return 0; 26 }
1 //使用组合bind函数,找出集合中大于5小于10的元素个数 2 #include <iostream> 3 #include <functional> 4 5 using namespace std; 6 7 auto f = std::bind(std::logical_and<bool>(),std::bind(std::greater<int>(),_1,5),std::bind(std::less_equal<int>(), _1, 10)); 8 9 int main(){ 10 set<int> se={1,2,3,4,5,6,7,8,9}; 11 int count = std::count_if(se.begin(), se.end(), f); 12 cout << count <<endl; 13 14 return 0; 15 }
std::bind需要注意的一些事项:(http://www.cnblogs.com/slysky/p/3822640.html)
1).std::bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的
2).对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的
3).bind的返回值是可调用实体,可以直接赋给std::function对象
4).对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的
5).类的this可以通过对象或者指针来绑定
C++11 学习笔记 std::function和bind绑定器
标签:
原文地址:http://www.cnblogs.com/yishuimao/p/5027890.html