Lambda表达式的完整声明格式如下:
[capture list] (params list) mutable exception-> return type { function body }
mutable指示符用来说明是否可以修改形参变量,exception表示异常设定
一个例子如下:
[capture list] (params list) -> return type {function body}
这个格式声明了const类型的表达式,这种类型不能修改括号中表面的形参
如果省略返回值的话:
[capture list] (params list) {function body}
如果body中存在return语句,则根据return语句的返回的值类型进行返回,如果没有return语句,则表示返回值为void
接下来我们举个例子,比如我们要对vector中的数进行倒序排序:使用lambda的好处就是,可以不用再额外定义函数
bool reverseSort(int a, int b) {
return a > b;
}
int main() {
vector<int> firstLev = { 3,5,1,2,6,4 };
vector<int> secondLev(firstLev);
sort(firstLev.begin(), firstLev.end(), reverseSort); //普通地调用排序函数
for (auto &a : firstLev) {
cout << a << " ";
}
cout << endl;
sort(secondLev.begin(), secondLev.end(), [](int a, int b) {return a > b; }); //通过lambda调用排序函数
for (auto &a : secondLev) {
cout << a << " ";
}
system("PAUSE");
}
外部变量的捕获:
Lambda表达式可以使用其可见范围内的外部变量,但必须明确声明(明确声明哪些外部变量可以被该Lambda表达式使用)。那么,在哪里指定这些外部变量呢?Lambda表达式通过在最前面的方括号[]来明确指明其内部可以访问的外部变量,这一过程也称过Lambda表达式“捕获”了外部变量。
值捕获:直接获取外部变量的值
//显式捕获
int a = 456;
auto f = [a]() {cout << a << endl; };
f();
引用捕获:捕获外部变量的引用
//引用捕获
auto z = [&a]() {cout << a << endl; };
z();
隐式捕获:根据lambda函数体内的变量情况,自动去捕获外部变量,括号内用一个等号表示
auto c = [=]() {cout << a << endl; };
c();
我们还可以让编译器根据函数体中的代码来推断需要捕获哪些变量,这种方式称之为隐式捕获。隐式捕获有两种方式,分别是[=]和[&]。[=]表示以值捕获的方式捕获外部变量,[&]表示以引用捕获的方式捕获外部变量。
捕获形式 | 说明 |
---|---|
[] | 不捕获任何外部变量 |
[变量名, …] | 默认以值得形式捕获指定的多个外部变量(用逗号分隔),如果引用捕获,需要显示声明(使用&说明符) |
[this] | 以值的形式捕获this指针 |
[=] | 以值的形式捕获所有外部变量 |
[&] | 以引用形式捕获所有外部变量 |
[=, &x] | 变量x以引用形式捕获,其余变量以传值形式捕获 |
[&, x] | 变量x以值的形式捕获,其余变量以引用形式捕获 |
使用mutable关键字修改被捕获的变量
auto h = [=]()mutable { cout << ++a << endl; };
cout << a << endl; //输出456,外部的值没有被修改
h(); //输出457,外部的值被修改