C++11 std::function及std::bind用法
类似于c语言中的函数指针,C++11中,提供了一个通用的描述方法,就是std::function。 std::function可以hold住任何可以通过“()”来调用的对象,包括:
- 普通函数
- 成员函数
- lambda
- std::bind
std::function的语法格式为:
template <class Ret, class... Args> class function<Ret(Args...)>;
先看一个简单的例子
void printNumber(vector<int>& number, function<bool (int)> filter) { for (const int& i : number) { if (filter(i)) { cout<<i<<endl; } } }
我们定义了一个printNumber函数,该函数有两个参数,一个是数组,一个是由std::function包装的---返回值为bool,参数为int的函数filter。
函数filter对传入数组number的每个成员进行操作并返回结果进行判断,那么该函数就可以通过改变filter的内容来实现各种不同的操作,如:
1 printNumber(numbers, [] (int i){ return i % 5 == 0;}); 2 printNumber(numbers, [] (int i){ return i > 20;});
第一行函数打印数组中 模5==0 的所有成员,而第二行函数打印数组中 >20 的所有成员。
这样利用std::function便能快速简洁的完成一些操作内容有重复的操作,而不用再去重复声明函数。
当然std::function的功能还有许多,如可以通过闭包将函数中内的内容传递出去,如:
void getMinMax(vector<int>& number, function<void ()>& printer) { int min = number.front(); int max = number.front(); for (int i : number) { if (i < min) { min = i; } if (i > max) { max = i; } } printer = [=] () { cout << "min:" <<min<< endl; cout << "max:" << max << endl; }; }
上例中我们构造了一个getMinMax函数,该函数找到参数数组number的最大值和最小值,并且对参数printer进行赋值,使其拥有了打印number最大值最小值的功能。
一般来说min和max两个局部变量在函数结束离开其作用域后便会释放,而printer捕获了这两个值,从而使得在之后的程序中调用printer便能打印出min和max。
在写程序的过程中,我们有时候无法预料到函数传入的参数到底是什么,而std::bind
可以将调用函数时的部分参数先制定好,留下一部分在真正调用时确定。
std::bind的语法格式为:
template<class Fn, class... Args> bind (Fn&& fn, Args&&... args);
有如下例子:
bool isTrue(int i,int min,int max){ return i>=min&&i<=max;}
假设我们仍用上面写过的函数printNumber,现在我们想用这个函数打印出 满足函数 bool isTrue(int i,int min,int max) 的所有数组成员。显然之前的std::function模板无法支持isTrue函数,
因此我们需要用到std::bind去绑定isTrue函数让其支持filter函数格式。假设我们现在需要打印出>=20并且<=50的成员。
std::bind(isTrue, placeholders::_1, 20, 50);function<bool(int)> filter = std::bind(isBetween, placeholders::_1, 20, 40);
printNumber(numbers, filter);
placeholders::_1 的意思是,这里是一个占位符,在调用的时候,将实际传递的第一个参数放到这里。
占位符的数量可以是任意多的,像这样:
std::placeholders::_1, std::placeholders::_2, …, std::placeholders::_N。
有时候我们在调用一些回调函数的时候,若该函数是类成员函数,我们不希望使用虚函数时,可以结合std::function和std::bind来实现回调。
class Printer { private: int min, max; public: Printer(int x, int y) { min = x; max = y; } void print() { cout << "min:" << min << endl; cout << "max:" << max << endl; } };
此处给出一个Printer类,假设我们需要调用其成员函数print
void usingCallback(function<void ()> print) { print(); }
我们可以通过下面的方法来调用print函数
Printer printer = Printer(10, 50); function<void ()> cb = bind(&Printer::print, printer); usingCallback(cb);
此处需注意,在绑定成员函数时,参数还需要一个类指针,因为成员函数参数默认均有一个this指针。
参考文章https://paul.pub/cpp-lambda-function-bind/