bind1st() ?和?bind2nd() ,在 C++11 里已经? deprecated 了,建议使用新标准的?bind() 。
头文件
#include <functional>
bind1st() 和bind2nd() 都是把二元函数转化为一元函数,方法是绑定其中一个参数。
bind1st() 是绑定第一个参数。
bind2nd() 是绑定第二个参数。
例子:
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
int main()
{
int numbers[] = { 10,20,30,40,50,10 };
int cx;
cx = count_if(numbers, numbers + 6, bind2nd(less<int>(), 40));
cout << "There are " << cx << " elements that are less than 40.\n";
cx = count_if(numbers, numbers + 6, bind1st(less<int>(), 40));
cout << "There are " << cx << " elements that are not less than 40.\n";
system("pause");
return 0;
}
结果: There are 4 elements that are less than 40. There are 1 elements that are not less than 40.
bind()
std::bind用来将可调用对象与其参数一起进行绑定。绑定后的结果可以使用std::function进行保存,并延迟调用到任何我们需要的时候。通俗来讲,它主要有两大作用:
- 将可调用对象与其参数一起绑定成一个仿函数。
- 将多元(参数个数为n,n>1)可调用对象转换为一元或者(n-1)元可调用对象,即只绑定部分参数。
绑定器函数使用语法格式如下:
// 绑定非类成员函数/变量 auto f = std::bind(可调用对象地址, 绑定的参数/占位符); // 绑定类成员函/变量 auto f = std::bind(类函数/成员地址, 类实例对象地址, 绑定的参数/占位符);
?下面来看一个关于绑定器的实际使用的例子:
#include <iostream>
#include <functional>
using namespace std;
void callFunc(int x, const function<void(int)>& f)
{
if (x % 2 == 0)
{
f(x);
}
}
void output(int x)
{
cout << x << " ";
}
void output_add(int x)
{
cout << x + 10 << " ";
}
int main(void)
{
// 使用绑定器绑定可调用对象和参数
auto f1 = bind(output, placeholders::_1);
for (int i = 0; i < 10; ++i)
{
callFunc(i, f1);
}
cout << endl;
auto f2 = bind(output_add, placeholders::_1);
for (int i = 0; i < 10; ++i)
{
callFunc(i, f2);
}
cout << endl;
return 0;
}
结果:
?0? 2? 4? 6? 8 10 12 14 16 18
在上面的程序中,使用了 std::bind 绑定器,在函数外部通过绑定不同的函数,控制了最后执行的结果。std::bind绑定器返回的是一个仿函数类型,得到的返回值可以直接赋值给一个std::function,在使用的时候我们并不需要关心绑定器的返回值类型,使用auto进行自动类型推导就可以了。
placeholders::_1 是一个占位符,代表这个位置将在函数调用时被传入的第一个参数所替代。同样还有其他的占位符 placeholders::_2、placeholders::_3、placeholders::_4、placeholders::_5 等……
有了占位符的概念之后,使得 std::bind 的使用变得非常灵活:
#include <iostream>
#include <functional>
using namespace std;
void output(int x, int y)
{
cout << x << " " << y << endl;
}
int main(void)
{
// 使用绑定器绑定可调用对象和参数, 并调用得到的仿函数
bind(output, 1, 2)();
bind(output, placeholders::_1, 2)(10);
bind(output, 2, placeholders::_1)(10);
// error, 调用时没有第二个参数
// bind(output, 2, placeholders::_2)(10);
// 调用时第一个参数10被吞掉了,没有被使用
bind(output, 2, placeholders::_2)(10, 20);
bind(output, placeholders::_1, placeholders::_2)(10, 20);
bind(output, placeholders::_2, placeholders::_1)(10, 20);
return 0;
}
示例代码执行的结果:
1 ?2?? ??? ?// bind(output, 1, 2)(); 10 2?? ??? ?// bind(output, placeholders::_1, 2)(10); 2 10?? ??? ?// bind(output, 2, placeholders::_1)(10); 2 20?? ??? ?// bind(output, 2, placeholders::_2)(10, 20); 10 20?? ??? ?// bind(output, placeholders::_1, placeholders::_2)(10, 20); 20 10?? ??? ?// bind(output, placeholders::_2, placeholders::_1)(10, 20);
通过测试可以看到,std::bind 可以直接绑定函数的所有参数,也可以仅绑定部分参数。在绑定部分参数的时候,通过使用 std::placeholders 来决定空位参数将会属于调用发生时的第几个参数。
?
|