码迷,mamicode.com
首页 > 其他好文 > 详细

C++11 学习笔记 std::function和bind绑定器

时间:2015-12-08 00:34:22      阅读:311      评论:0      收藏:0      [点我收藏+]

标签:

一.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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!