c++ Lambda 函数形式及用法

来源:互联网 发布:淘宝抱枕推荐 编辑:程序博客网 时间:2024/06/03 23:00

声明:本文参考了 http://www.cnblogs.com/lidabo/p/3908663.html 和 https://www.zhihu.com/question/20125256
Lambda函数又称lambda函数和匿名函数,是c++11新加入的一个十分强大的特性。在编程中经常可以用到。

基本用法形式

我们可以这样定义一个Lambda函数:
#include <iostream>
int main(){
auto f1 = [] () { std::cout << "I am Lambda"; };//省略函数类型
auto f2 = [] () -> int {
std::cout << "I am Lambda too";
return 1;
};//函数类型后置
}

其中f1即可调用或者作为参数被传入(类似于函数指针的作用)。auto可以自动获得f1的类型,依据f1函数体中返回值的类型来判断,若无返回,则为void。也可以显式指定返回类型如f2,需用函数类型后置。
也可以这样子在传参时进行定义:
#include <iostream>
void func(std::function<void(int &)>) {
//函数体
}
int main() {
func([] (int &a) {
std::cout << "a is using" << std::endl;
});
}

总的来说,Lambda表达式的形式为:
[captures] (params) -> ret {Statments;}

[]用于截取外部信息,可以使函数使用外部作用域的变量。先假设外部有x,y两个变量,则可有下列选项:

  • [] 不截取任何变量
  • [x] 截取x变量并且拷贝一份在函数体重使用,同时不截取其他变量
  • [&x] 截取x变量并作为引用在函数体重使用,同时不截取其他变量
  • [=] 截取外部作用域中所有变量x,y,并拷贝一份在函数体中使用
  • [&] 截取外部作用域中所有变量x,y,并作为引用在函数体中使用
  • [=, &x] 截取外部作用域中所有变量x,y,并拷贝一份在函数体中使用,但是对x变量使用引用
  • [this] 截取当前类中的this指针。如果已经使用了&或者=就默认添加此选项。

() 是传参列表,与普通函数的参数列表极其相似。
->ret 即函数类型可以省略,也仅有此项可以省略。
{} 为函数体

用处,好处

就比如:
Storage{
list<Meeting> ms;
};

这时候想在public中设计一个通过name或者时间来查询会议的方法时,就必须提供一个接口来让用户自定义查询方法。实现如下:
Storage{
list<Meeting> ms;
public:
list<Meeting> queryMeeting(function<bool(const Meeting &)>) {
//遍历查询并返回
}
};
要使用时:
storage.query([&name] (const Meeting &t) {
if(name == t.getName()) return true;
else return false;
});//通过名字查询
storage.query([&date] (const Meeting &t) {
if(date == t.getDate()) return true;
else return false;
});//通过时间查询

另外,在我们程序中,经常有这样一些需求:
1. 需要一个临时方法,这个方法只会使用一次,或者使用的很少。
2. 这个方法的方法体很短,以至于比方法声明都短,写起来感觉大材小用。
这个时候Lambda就可以大显身手了。简单来说,编程中提到的 lambda 表达式,通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用(此处尤其指上文提到的第二种定义方法)。不用多定义一个(污染环境的)函数,尤其如果这个函数只会使用一次的话。而且更易读,因为那个映射到列表上的函数具体是要做什么,非常一目了然。例子如下:
当你想改变一个vector的时候,原来你得这么写:
vector<int> v;
v.push_back( 1 );
v.push_back( 2 );
//...
for ( auto itr = v.begin(), end = v.end(); itr != end; itr++ ) {
*itr++;
}

用Lambda则为:
vector<int> v;
v.push_back( 1 );
v.push_back( 2 );
//...
for_each( v.begin(), v.end(), [] (int &val) { val++; });

这么写了之后更清晰,方便,而且执行效率反而提高了。因为编译器有可能使用”循环展开“来加速执行过程。

原创粉丝点击