0x00 前言
文章中的文字可能存在语法错误以及标点错误,请谅解;
如果在文章中发现代码错误或其它问题请告知,感谢!
0x01 lambda表达式的概念及声明
1.lambda概念
lambda表达式在C++11中被引用,其主要作用是可以不需要为一段逻辑代码而去专门命名一个函数名,并且可以捕获一定范围内的变量,可以方便定义和创建匿名函数,让程序具有更好的可读性和维护性。
2.lambda声明
lambda表达式的语法形式如下:
[capture list] (params list) mutable exception-> return type { function body }
capture list
:捕获外部变量列表
params list
:形参列表,类似普通函数中的参数
mutable
:用来修饰值捕获的外部变量
exception
:异常设定
return type
:返回类型
function body
:函数体
一个lambda表达式举例如下:
auto value = [](int input)->int{return ++input;};
std::cout << value (1) << std::endl; //输出2
该表达式表示不捕获任何外部变量,只将输入input自加1并返回。
有时候,当lambda返回值很明显可以则可以省略return type
:
auto value = [](int input){return ++input;};
std::cout << value (1) << std::endl; //输出2
我们可以省略某些lambda表达式某些部分来实现功能,常见的情况有以下几种:
常见形式 | 解释 |
---|---|
[capture list] (params list) -> return type {function body;}; | 省略了用来修饰值捕获的外部变量,表示声明const类型表达式,不能修改捕获列表中的值 |
[capture list] (params list) {function body;}; | 省略了返回值类型,但编译器可以根据funciton body中的return推断返回值类型,若没有return则返回值类型为void |
[capture list] {function body;}; | 省略了参数列表,可以看成无参函数 |
例如当lambda表达式没有形参列表时,可以省略params list
,例如:
auto value1 = [](){return 1;};
auto value2 = []{return 1;};
0x02 lambda表达式捕获列表
lambda表达式可以通过捕获列表capture list
获取指定范围内的变量:
[]
:不捕获任何变量。
[&value]
按引用捕获 value变量,同时不捕获其他变量。
[=value]
按值捕获 value变量,同时不捕获其他变量。
[&]
捕获外部作用域中所有变量,并作为引用在函数体function body
中使用(按引用捕获)。
[=]
捕获外部作用域中所有变量,并作为副本在函数体function body
中使用(按值捕获)。
[=,&value]
按值捕获外部作用域中所有变量,并按引用捕获 value变量。
[this]
捕获当前类中的 this 指针,让 lambda 表达式拥有和当前类成员函数同样的访问权限。如果已经使用了 & 或者 =,就默认添加此选项。捕获 this 的目的是可以在 lamda 中使用当前类的成员函数和成员变量。
举例:
例1:引用捕获
#include<iostream>
using namespace std;
int main()
{
int value = 123;
auto f = [&value] { cout << value << endl; };
value = 321;
f();
}
结果:
321
例2:值捕获
#include<iostream>
using namespace std;
int main()
{
int value = 123;
auto f = [=value] { cout << value << endl; };
value = 321;
f();
}
结果:
123
在这个例子中,lambda表达式按值捕获了所有外部变量,在捕获一瞬间,value的值就已经被复制到f中,之后value被修改,但是f中存储的值value仍然还是捕获时的值,因此结果输出时123。
例3:修改捕获变量
#include<iostream>
using namespace std;
int main()
{
int value = 123;
//auto f1 = [=](){ cout << ++value << endl; }; //报错,修改按值捕获的外部变量
auto f2 = [=]()mutable { cout << ++value << endl; };
f2();
}
结果:
124
例4:隐式捕获
#include<iostream>
using namespace std;
int main()
{
int value = 123;
auto f1 = [=] { cout << value << endl; };
auto f2 = [&] { cout << value << endl; };
value = 321;
f1();
f2();
}
结果:
123
321
例2例3中值捕获或引用捕获都需要确定需要捕获的变量,我们还可以让编译器根据函数体中的代码推断需要捕获哪些变量,该方式称为隐式捕获,[=]表示按值捕获方式捕获外部变量,[&]表示按引用捕获方式捕获外部变量。
0x03 lambda表达式实例
例5:从小到大排列
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool cmp(int a, int b)
{
return a < b;
}
int main()
{
vector<int> vec{ 3, 2, 5, 7, 3, 2 };
vector<int> lambdavec(vec);
sort(vec.begin(), vec.end(), cmp);
cout << "common:" << endl;
for (int it : vec)
cout << it << ' ';
cout << endl;
sort(lambdavec.begin(), lambdavec.end(), [](int a, int b) -> bool { return a < b; }); // Lambda表达式
cout << "lambda:" << endl;
for (int it : lambdavec)
cout << it << ' ';
}
结果:
common:
2 2 3 3 5 7
lambda:
2 2 3 3 5 7
以上。
参考文档:
1.http://c.biancheng.net/view/3741.html
2.https://www.cnblogs.com/DswCnblog/p/5629165.html