bind标准库函数,定义在头文件functional中。可以将bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
调用bind的一般形式为:
auto newCallable = bind(callable,arg_list);
其中,newCallable是一个可调用对象,arg_list是逗号分隔的参数列表,对应callable的参数。当我们调用newCallable时,newCallable会调用callable,并传递arg_list中的参数。
arg_list中可能会包含形如_n的参数,n是一个整数,这些参数是占位符,表示newCallable的参数占据传递给newCallable的参数的位置。_1为newCallable的第一个参数,_2为newCallable的第二个参数,以此类推。
_n在placeholders命名空间内,需要使用usingnamespace std::placeholders;
可以用bind绑定给定的可调用对象的参数或调整其参数顺序。比如f是一个有5个参数的可调用对象,auto g = bind(f, a, b, _2, c, _1); 调用g时,第一个参数传递给f做第五个参数,第二个参数传递给f做第三个参数。
默认情况下,bind中不是占位符的参数被拷贝到bind返回的可调用对象中。但是,有时候有些参数要以引用方式传递或者参数类型不允许拷贝,比如ostream对象。这时就需要用ref标准库函数,ref函数返回一个对象,包含指定的引用,该对象是可拷贝的。
#include < functional>
using namespace std;
using namespace std::placeholders;
int Func(int x, int y);
auto bf1 = bind(Func, 10, _1);
bf1(20); // same as Func(10, 20)
class A
{
public:
int Func(int x, int y);
};
A a;
auto bf2 = bind(&A::Func, a, _1, _2);
bf2(10, 20); // same as a.Func(10, 20)
function< int(int)> bf3 = bind(&A::Func, a, _1, 100);
bf3(10); // same as a.Func(10, 100)
上面的例子中,bf1是把一个两个参数普通函数的第一个参数绑定为10,生成了一个新的一个参数的可调用实体; bf2是把一个类成员函数绑定了类对象,生成了一个像普通函数一样的新的可调用实体; bf3是把类成员函数绑定了类对象和第二个参数,生成了一个新的function对象。使用bind需要注意的一些事项:
•(1)bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的
•(2)对于不事先绑定的参数,需要传占位符进去,从_1开始,依次递增。placeholder是pass-by-reference的
•(3)bind的返回值是可调用实体,可以直接赋给std::function对象
•(4)对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的
•(5)类的this可以通过对象或者指针来绑定
bind是这样一种机制,它可以预先把指定可调用实体的某些参数绑定到已有的变量,产生一个新的可调用实体。C++98中,有两个函数bind1st和bind2nd,它们分别可以用来绑定functor的第一个和第二个参数,它们都是只可以绑定一个参数。各种限制,使得bind1st和bind2nd的可用性大大降低。C++0x中,提供了std::bind,它绑定的参数的个数不受限制,绑定的具体哪些参数也不受限制,由用户指定,这个bind才是真正意义上的绑定,有了它,bind1st和bind2nd就没啥用武之地了,因此C++0x中不推荐使用bind1st和bind2nd了,都是deprecated了。