lambda表达式(自 C++11 起)
功能
构造闭包:构造一个未命名的函数对象,能够捕获作用域中的变量。
闭包(匿名函数):能够读取其他函数内部变量的函数。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
用于替代一些功能比较简单,但又有大量使用的函数,可以使用lambda搭配STL算法如sort(),genrate()等函数,来实现想要的效果。
语法
[ 捕获 ] ( 参数列表 ) 说明符 -> 返回类型 { 函数体; };
捕获
获取当前作用域中的变量。捕获是零个或多个捕获的逗号分隔列表,可以选择以捕获默认值开头。捕获列表定义了可从 lambda 函数体内部访问的外部变量。
捕获的方式为:
- &(通过引用隐式捕获使用的自动变量)
- =(通过复制隐式捕获使用的自动变量)
捕获方式 | 说明 |
---|---|
[] | 默认不捕获任何变量 |
[=] | 默认以复制捕获所有变量 |
[&] | 默认以引用捕获所有变量 |
[x] | 仅以复制捕获x,其它变量不捕获 |
[x…] | 以包展开方式复制捕获参数包变量 |
[&x] | 仅以引用捕获x,其它变量不捕获 |
[&x…] | 以包展开方式引用捕获参数包变量 |
[=, &x] | 默认以复制捕获所有变量,但是x是例外,通过引用捕获 |
[&, x] | 默认以引用捕获所有变量,但是x是例外,通过复制捕获 |
[this] | 通过引用捕获当前对象(其实是复制指针)(C++20起) |
[*this] | 通过复制方式捕获当前对象(C++17 起) |
参数列表
默认为空,与普通函数传参方式相同
说明符
如果未提供,则副本捕获的对象在 lambda 主体中是 const。在每个序列中,最多允许使用一次说明符:
- mutable:允许函数体修改由 copy 捕获的对象,并调用其非 const 成员函数。当lambda要修改值捕获的变量时,必须添加mutable声明。
返回类型
lambda的返回类型。lambda会自动推断返回值类型,也可以显示指明返回类型。
函数体
和普通函数函数体相同。
示例
- 使用lambda定义一个普通匿名函数,使用auto自动推断变量类型(lambda函数类型唯一)
auto lambdaTest= []() {std::cout << "This is a lambda test." << std::endl;};
lambdaTest();
- 使用值传递x,使用引用传递y,lambda自动推断返回值。
int y=1;
double x=2.5;
auto lambdaTest= [x, &y]() {
//x++; 报错,x为只读
y++;
std::cout << x << "+" << y << "=" << x+y << std::endl;
return x+y;
};
std::cout<< lambdaTest() <<std::endl;
std::cout<< y <<std::endl; // y值改变
- 自动推断返回类型,mutable关键字使得值传递变量可修改,它的修改出了lambda表达式以后就无效了。
double x=2.5;
int y = 1;
auto lambdaTest = [y, &x] (double a, int b) mutable {
y = y+2; //y值在此作用域内可改变,因为mutable关键字
x = x+5;
std::cout << x << " "<< y << std::endl; // 7.5 3
return a + b + x;
};
std::cout<< lambdaTest(1.3, 2) <<std::endl; // 10.8
std::cout<< x << " " << y <<std::endl; // 7.5 1 ;x值改变, y值不改变
- 指定返回类型,使用值传递所有参数(x例外,为引用传递)
double x=2.5;
int y = 1,z=2;
auto lambdaTest = [=, &x] (double a, int b) mutable->int {
z++; //不报错
x = x+5;
std::cout << x+y+z << std::endl; // 11.5
return a + b + x;
};
std::cout<< lambdaTest(1.3, 2) <<std::endl; // 10 ;类型转换
- 与sort()配合使用,实现根据数据第二个数从小到大排序。
vector< vector<int> > v_test = { {0,1},{3,5}, {2,3} , {4,0} };
sort(v_test.begin(),v_test.end(),[](vector<int>&a, vector<int>&b){return a[1]<b[1];});
for(auto &x:v_test)
{
std::cout << x[0] << " "<< x[1]<<endl; //输出结果
}
Tips
- lambda无法捕获任何具有静态存储持续时间的变量
- auto lambdaTest= [=,x]{return 1;} ; //错误,使用了值传递后面不能重复使用
- auto lambdaTest= [&,&x]{return 1;}; //错误,使用了引用传递后面不能重复使用