C++ bind详解

   bind是一组用于函数绑定的模板。在对某个函数进行绑定时,可以指定部分参数或全部参数,也可以不指定任何参数,还可以调整各个参数间的顺序。对于未指定的参数,可以使用占位符_1、_2、_3来表示。-1表示绑定后的函数的第1个参数,_2表示绑定后的函数的第2个参数,其他依次类推。
    bind可以绑定到普通函数、函数对象、类的成员函数和类的成员变量。下面分别进行介绍。
    1、普通函数
1 void nine_arguments(int i1,int i2,int i3,int i4,int i5,int i6,int i7,int i8,int i9);
2 int i1=1, i2=2, i3=3, i4=4, i5=5, i6=6, i7=7, i8=8, i9=9;
3 bind(nine_arguments,_9,_2,_1,_6,_3,_8,_4,_5,_7(i1,i2,i3,i4,i5,i6,i7,i8,i9);
4 bind(nine_arguments,i9,i2,i1,i6,i3,i8,_1,_2,_1)(i8,i9);
5 bind(nine_arguments, i9,i2,i1,i6,i3,i8,i4,i5,i7)();
    2、函数对象  
1 class CStudent
2 {
3 public:
4             void operator() (string strName, int nAge)
5             {
6                 cout << strName << " : " << nAge << endl; 
7             }
8 };
9 bind(CStudent(), "Mike", _1)(12);
    3、类的成员函数
 1 struct TAdd
 2 {
 3     int Add(int x,int y)
 4     {
 5         return x+y;
 6     }
 7 };
 8 TAdd tAdd;
 9 TAdd *p = new TAdd();
10 shared_ptr<TAdd> *q(p);
11 bind(TAdd::Add, tAdd, 2, 3)();
12 bind(TAdd::Add, p, 2, 3)();
13 bind(TAdd::Add, q, 2, 3)();
    4、类的成员变量
1 void Output(const string &name)
2 {
3       cout << name << endl;
4 }
5 
6 map<int, string> map1;
7 for_each(map1.begin(), map1.end(), bind(Output, bind(map<int,              
8       string>::value_type::second, _1)));
    bind还可以进行嵌套绑定。假设有一个CPerson类,该类有一个获取年龄的接口int GetAge(),现在有一个CPerson对象的vector,需要对其进行排序,则可以如下使用bind
1 vector<CPerson> vctPerson;
2 sort(vctPerson.begin(), vctPerson.end(), bind(less<int>(), 
3 bind(CPerson::GetAge, _1), bind(CPerson::GetAge, _2)));
    假设有一个整数的vector, 现在想要获取其中大于20但小于30的整数的个数,则有:
1 count_if(vctNum.begin(),  vctNum.end, bind(logic_and<bool>(), 
2     bind(greater<int>(), _1, 20), bind(less<int>(), _1, 30)));
    在使用bind时,还有一些需要特别注意的地方,下面逐一进行介绍。
    1、对于指定了值的参数,bind返回的函数对象会保存这些值,并且缺省是以传值方式保存的。考虑下面的代码:
1 void inc(int &a)            { a++; }
2 int n = 0;
3 bind(inc, n)();
    调用bind返回的函数对象后,n仍然等于0。这是由于bind时,传入的是n的拷贝。如果需要传入n的引用,则可以使用ref或cref函数,比如:
1 bind(inc, ref(n))();            // n现在等于1了
    2、bind的第一个参数是一个函数对象,不能用占位符来代替。考虑下面的代码:
1 typedef function<void (int)> Func;
2 vector<Func> vctFunc;
3 for_each(vctFunc.begin(), vctFunc.end(), bind(_1, 5));         // 编译出错
    此时,可以借助apply模板。apply模板的第一个参数是传入的函数对象,后面可以有若干个参数,表示函数对象的参数。比如:
1 apply<void>  a;                // void是函数对象的返回值类型
2 a(f);                                 // 相当于调用f()
3 a(f, x);                             // 相当于调用f(x)
4 a(f, x, y);                         // 相当于调用f(x, y)
    使用apply后,我们可以将vctFunc中的元素当作占位符传递过来。参考代码如下:
1 for_each(vctFunc.begin(), vctFunc.end(), bind(apply<void>(), _1, 5));

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
std::bindC++11引入的函数对象适配器,用于将函数对象(包括普通函数、成员函数、函数指针等)与其参数进行绑定,生成一个新的函数对象。 它的基本语法如下: ```cpp template< class Fn, class... Args > bind( Fn&& fn, Args&&... args ); ``` 其中,Fn表示要绑定的函数对象(可以是普通函数、成员函数、函数指针等),Args表示要绑定的参数。 使用std::bind可以实现参数的绑定、参数重排、占位符等功能。下面是一些示例: 1. 绑定普通函数: ```cpp #include <iostream> #include <functional> void foo(int a, int b) { std::cout << "a + b = " << a + b << std::endl; } int main() { auto func = std::bind(foo, 1, 2); func(); // 输出:a + b = 3 return 0; } ``` 2. 绑定成员函数: ```cpp #include <iostream> #include <functional> class Foo { public: void bar(int a, int b) { std::cout << "a + b = " << a + b << std::endl; } }; int main() { Foo obj; auto func = std::bind(&Foo::bar, &obj, 1, 2); func(); // 输出:a + b = 3 return 0; } ``` 3. 参数重排: ```cpp #include <iostream> #include <functional> void foo(int a, int b) { std::cout << "a + b = " << a + b << std::endl; } int main() { auto func = std::bind(foo, std::placeholders::_2, std::placeholders::_1); func(2, 1); // 输出:a + b = 3 return 0; } ``` 在这个示例中,使用std::placeholders::_1和std::placeholders::_2来表示占位符,表示在调用func时,第一个参数将会被传递给foo的第二个参数,第二个参数将会被传递给foo的第一个参数。 这些仅是std::bind的一些基本用法,它还提供了更多的功能和特性,可以根据具体需求进行学习和使用。希望能对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值