导言
bind是这样一种机制,它可以将参数绑定于可调用对象,产生一个新的可调用实体,这种机制在函数回调时颇为有用。C++98中,有两个函数bind1st和bind2nd,它们分别用来绑定functor的第一个和第二个参数,都只能绑定一个参数。C++98提供的这些特性已经由于C++11的到来而过时,由于各种限制,我们经常使用bind而非bind1st和bind2nd。在C++11标准库中,它们均在functional
头文件中。而C++STL很大一部分由Boost库扩充,STL中的shared_ptr等智能指针,bind及function都是由Boost库引入。在写代码过程中,要养成使用bind,function,lambda和智能指针的习惯,它们非常强大简洁实用。
正文
1. 过时的bind1st和bind2nd
bind1st(op, arg) :op(arg, param)
bind2nd(op, arg) :op(param, arg)
vector<int> coll {1, 2, 3, 4, 5, 11, 22, 5, 12};
// 查找第一个元素值大于10的元素
std::find_if(coll.begin(), coll.end(), // range
std::bind2nd(std::greater<int>(), 10));
// 查找元素值大于10的元素的个数
int _count = count_if(coll.begin(), coll.end(), // range
std::bind1st(less<int>(), 10)/*判断准则*/);
2. C++11中的std::bind
/*function object内部调用plus<>(也就是operator+),以占位符(placeholders)_1为第一个参数,以10为第二个参数,占位符_1表示实际传入此表达式的第一实参,返回“实参+10”的结果值*/
auto plus10 = std::bind(std::plus<int> (), std::placeholders::_1, 10);
std::cout << plus10(7) << std::endl;// 17
// (x + 10)*2,下面的代码中x=7
std::bind(std::multiplies<int>(),
std::bind(std::plus<int>(), std::placeholders::_1, 10),// i+10
2)(7);
注意:上面所用的less<int>(), greater<int>()以及plus<int>()
等都是C++预定义的Function Object。因此我们可以知道,bind可以把参数绑定到“函数对象”上。除此之外,bind()还可以把参数绑定到普通函数、类成员函数、甚至数据成员等。
3. 使用std::bind要注意的地方
- bind预先绑定的参数需要传具体的变量或值进去,对于预先绑定的参数,是pass-by-value的;
- 对于不事先绑定的参数,需要传std::placeholders进去,从_1开始,依次递增。placeholder是pass-by-reference的;
- bind的返回值是可调用实体,可以直接赋给std::function对象;
对于绑定的指针、引用类型的参数,使用者需要保证在可调用实体调用之前,这些参数是可用的; - 类的this可以通过对象或者指针来绑定
4. 何时使用std::bind
- 你需要绑定一个调用到一个
普通函数
,使用部分或全部参数 - 你需要绑定一个调用到一个
成员函数
,使用部分或全部参数 - 你需要
嵌套组合
函数对象(比如x>5&&x<10, (i+10)*2)