std::bind用来将可调用对象与其参数一起进行绑定。绑定后的结果可以使用std::function进行保存,并延迟调用到任何我们需要的时候。通俗来讲,它主要有两大作用:
1.将可调用对象与其参数一起绑定成一个仿函数。
2.将多元(参数个数为n,n>1)可调用对象转换为一元或者(n-1)元可调用对象,即只绑定部分参数。
绑定器函数使用语法格式如下:
// 绑定非类成员函数/变量
auto f = std::bind(可调用对象地址, 绑定的参数/占位符);
// 绑定类成员函/变量
auto f = std::bind(类函数/成员地址, 类实例对象地址, 绑定的参数/占位符);
下面来看一个关于绑定器的实际使用的例子(auto f = std::bind(可调用对象地址, 绑定的参数/占位符)):
#include <iostream>
#include <string>
#include<functional>
using namespace std;
//第三个参数是包装器类型,传递的实参应该是可调用对象,用绑定器得到可调用对象
//用绑定器对output_add函数进行绑定,得到可调用对象,再传递给testFunc
void testFunc(int x, int y, const function<void(int, int)> &f) {
if (x % 2 == 0) {
f(x, y);
}
}
void output_add(int x, int y) {
cout << "x:" << x << ",y:" << y << ",x+y:" << x + y << endl;
}
int main() {
for(int i=0;i<10;i++){
auto f=bind(output_add,i+100,i+200);
testFunc(i,i,f);//f是可调用对象类型
auto f2= bind(output_add,placeholders::_1,placeholders::_2);
testFunc(i,i,f2);//使用占位符,testFunc(i,i,f2)
}
return 0;
}
std::bind绑定器返回的是一个仿函数类型,得到的返回值可以直接赋值给一个std::function,在使用的时候我们并不需要关心绑定器的返回值类型,使用auto进行自动类型推导就可以了。
placeholders::_1是一个占位符,代表这个位置将在函数调用时被传入的第一个参数所替代。同样还有其他的占位符placeholders::_2、placeholders::_3、placeholders::_4、placeholders::_5等……
下面来看一个关于绑定器的实际使用的例子(auto f = std::bind(类函数/成员地址, 类实例对象地址, 绑定的参数/占位符)),如果绑定的是成员,那么第三个参数可以省略:
#include <iostream>
#include <string>
#include<functional>
using namespace std;
class Test {
public:
void output(int x, int y) {
cout << "x:" << x << ",y:" << y << endl;
}
int m_number = 100;
};
int main() {
//成员函数绑定
Test t;
//类函数地址:&Test::output
// 类实例对象地址:&t
// 绑定的参数:520和placeholders::_1
auto f3 = bind(&Test::output, &t, 520, placeholders::_1);//绑定器绑定完后是一个仿函数
//output返回void
function<void(int, int)> f33 = bind(&Test::output, &t, 520, placeholders::_1);//f33将仿函数进行包装,得到了包装器类型,f3与f33不等价
f3(1314);//第一个参数已经指定了
//成员变量绑定
//成员变量没有参数,第三个参数省略
auto f4 = bind(&Test::m_number, &t);//绑定器绑定完后是一个仿函数
function<int &(void)> f44 = bind(&Test::m_number, &t);//f44将仿函数进行包装,得到了包装器类型,f4与f44不等价
cout << f4() << endl;//f4()代表类成员函数
f4() = 777;
cout << f4() << endl;
return 0;
}
总结:
在用绑定器绑定类成员函数或者成员变量的时候需要将它们所属的实例对象一并传递到绑定器函数内部。
使用绑定器绑定的类成员变量m_number得到的仿函数被存储到了类型为function<int&(void)>的包装器对象中,并且可以在需要的时候修改这个成员。其中int是绑定的类成员的类型,并且允许修改绑定的变量,因此需要指定为变量的引用,由于没有参数因此参数列表指定为void。
示例程序中是使用function包装器保存了bind返回的仿函数,如果不知道包装器的模板类型如何指定,可以直接使用auto进行类型的自动推导,这样使用起来会更容易一些。