std::function
上文中,对于分两次,打印出一个vector集合中,所有:
1. 模 5 = 0
2. 大于 20
的数字。
这个需求,我们的实现其实还不够好。
回头看一下printNumber1和printNumber2这两个函数,这两个函数大部分都是重复的:它们都需要遍历集合,都需要做if判断,然后打印出结果。
实际上,我们在项目中经常遇到这个的问题:
两(多)个函数,有大部分的代码都是一样的,其中只有一两行代码有不一样的地方。
其实,我们可以对这个不一样的地方,再做一个抽象,把它们共通起来。
具体到这个例子就是:无论是“模 5 = 0”还是“大于 20”都是满足“某种条件”。
而很自然的会想到,我们是否可以通过一个类似这样的函数来做这个判断:
bool func(int i)
然后实现两个函数,通过函数指针的形式来完成判断就好了。
但是,我们马上又意识到,这两个函数会很小,并且也是只会用一遍而已,定义一个函数又太“浪费”了。 很自然的,我们就会想lambda。但是,lambda似乎没法转成函数指针。。。
C++11中,提供了一个通用的描述方法,就是std::function。 std::function可以hold住任何可以通过“()”来调用的对象,包括:
普通函数 成员函数 lambda std::bind(见下文)后的结果std::function的语法是这样:
template <class Ret, class... Args> class function<Ret(Args...)>;
例如:function<bool (int)> filter 就表达了我们前面需要的那个函数:这个函数接受一个int值作为参数,同时返回一个bool作为判断的结果。但同时,我们可以用lambda表达式直接传递进去。
因此,上面的代码可以改写成这样:
void printNumber(vector<int>& number, function<bool (int)> filter) {
for (const int& i : number) {
if (filter(i)) {
cout<<i<<endl;
}
}
}
然后在需要的地方,这样调用即可:
printNumber(numbers, [] (int i){ return i % 5 == 0;});
printNumber(numbers, [] (int i){ return i > 20;});
这种做法,是不是又简洁了不少?
闭包
前面提到了“闭包”这个词,这里我们来聊一下闭包。
下面是维基百度对于闭包的定义:
在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。 这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。
简单来说:闭包可以记忆住创建它时候的那些变量。










