前言
lambda表达式又被称之为lambda函数,是c++11的新特性,下面我们看一下lambda表达式的参数等说明:
[函数对象参数](操作符重载函数参数)mutable或exception声明->返回值类型{
函数体
}
下面我们说明一下参数类型以及变量截取规则:
1.[函数对象参数]:捕捉列表。捕捉列表总是出现在lambda函数的开始处,[]是lambda函数的引出符,这个必须存在不可以省略。编译器会根据引出符判断接下来的代码是否是Lambda函数。捕捉列表能够捕捉上下文中的变量以供Lambda函数使用。
2.函数对象参数形式列表:
空。没有任何函数对象参数。
=。函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
&。函数体内可以使用 Lambda 所在范围内所有可见的局部变量(包括 Lambda 所在类的 this),并且是引用传递方式相当于是编译器自动为我们按引用传递了所有局部变量)。
this。函数体内可以使用 Lambda 所在类中的成员变量。
a。将 a 按值进行传递。按值进行传递时,函数体内不能修改传递进来的 a 的拷贝,因为默认情况下函数是 const 的,要修改传递进来的拷贝,可以添加 mutable 修饰符。
&a。将 a 按引用进行传递。
a,&b。将 a 按值传递,b 按引用进行传递。
=,&a,&b。除 a 和 b 按引用进行传递外,其他参数都按值进行传递。
&,a,b。除 a 和 b 按值进行传递外,其他参数都按引用进行传递
3.[操作符重载函数参数] : 标识重载的 () 操作符的参数,没有参数时,这部分可以省略,可以连同括号“()”一起省略。
参数可以通过按值(如: (a, b))和按引用 (如: (&a, &b)) 两种方式进行传递。
4.mutable 或 exception 声明 :mutable 可变变量,exception 异常
注:在使用该修饰符时,参数列表不可省略(即使参数为空);
5.[返回值类型] :返回类型,当不需要返回类型时(void),可以省略
6.[函数体] : 函数内容,可以使用上下文的数据。
一、lambda函数实例
#include <iostream> using namespace std; int main() { auto func = [](){cout<<"hello Lambda"; }; func(); }
在上图中func就是一个lambda函数,我们使用auto来自动获取func的类型,这一步非常重要,当我们定义好lambda函数之后,就可以当正常函数来使用了。[]表示接下来定义lambda函数,正常情况下只要函数体所有return都是同一个类型的话,编译器就会自行判断函数的返回类型,也可以显式的指定lambda函数的返回类型,这就需要用到函数返回值后置的功能,比如下面这个代码:
[]()->int{return 1;}
那么lambda函数有什么用呢?假如我们设计的一个类需要提供函数查询这个类,可能会根据多种情况查询,还有可能两者结合,我们如果为每个情况都写个函数,那么一定显得很冗余,这个时候就可以用lambda函数来实现这个功能,只需要提供一个接口让用户方便的自定义自己的查询方式。
Lambda函数和STL有什么关系呢?lambda函数的引入为STL的使用提供了极大的方便,就比如下面这个例子,以前我们想遍历一个vector的时候是下面这样的:
int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); v.push_back(5); vector<int>::iterator it = v.begin(); for(auto ptr = it;ptr!=v.end();ptr++) { cout<<*ptr; } }
当我们用lambda后变成了这样:
int main() { vector<int> v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); v.push_back(5); for_each(v.begin(),v.end(),[](int val) { cout<<val; } ); }
我们用lambda表达式这样的写法可以提高代码的执行效率,因为编译器有可能使用"循环展开"来加速执行过程。
总结
lambda 表达式就是一个函数(匿名函数),也就是一个没有函数名的函数。为什么不需要函数名呢,因为我们直接(一次性的)用它,嵌入式用的它,不需要其他地方调用它。lambda表达式也叫闭包。闭就是封闭的意思(封闭就是其他地方都不调用它),包就是函数。lambda表达式其实就是一个函数对象,他内部创建了一个重载()操作符的类。lambda的引入给我们带来了一种全新的编程体验,使我们从繁琐的语法中解放出来,更加关注于 “算法” 本身。