C++11中lambda、std::function和std:bind详解

2020-01-06 16:42:25王振洲

下面,我们再通过一个例子来说明。

现在,假设我们的需求是:获取一个集合中最小和最大值,并在稍后的时候(可能是另外一个函数中)打印它们。 这里,我们常规的做法通常是:通过一个函数获取集合的最大,最小值,然后保存住,最后在需要的时候访问这两个值,然后打印它们。
这样做就会需要解决:如果保存和传递最大,最小这两个值。

但实际上,这里我们可以考虑用闭包来实现这个功能,让闭包把最大,最小两个值捕获下来,然后在需要的地方调用就可以了。

请看一下下面这段代码:


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;
 };
}

这里,我们通过function<void ()>& printer(如果你看不懂function,请看上文)传递出这个闭包。 然后,在需要的地方,这样即可:


function<void()> printer;
getMinMax(numbers, printer);
......

printer();

这里的printer其实是我们前面从getMinMax函数出传出的闭包,这个闭包捕获了min和max。我们直接传递这个闭包给需要的地方使用,而不用传递裸的两个数值,是不是优雅的不少?

std::bind

下面,我们再改进一下需求,假设我们要

打印出vector<int>中,20<x<40范围内的值 ,该怎么办?

毕竟,bool isBetween(int i, int min, int max) 这个函数可没法对应上

function<bool (int)> filter 啊!参数数量就不一样嘛。

这个时候,我们可以用 std::bind 。

std::bind的语法是这样的:


template <class Fn, class... Args> bind (Fn&& fn, Args&&... args);
template <class Ret, class Fn, class... Args> bind (Fn&& fn, Args&&... args);

std::bind可以将调用函数时的部分参数先指定好,留下一部分在真正调用的时候确定。

(当然,你也可以直接指定全部参数,在调用时不再指定。)

这里,isBetween中,最小,最大值其实我们是确定了的,即:20和40。而不确定的,其实是真正待判断的数字本身,那么我们就可以这么做:

std::bind(isBetween, placeholders::_1, 20, 40);

placeholders::_1 的意思是,这里是一个占位符,在调用的时候,将实际传递的第一个参数放到这里。

占位符的数量可以是任意多的,像这样: