C++ Lamda表达式
Lambda表达式是什么?
Lambda是C++11之后新增的匿名函数表达式,使用它可以很方便的定义匿名函数,通常匿名函数的代码行数都是比较少的时候才用,方便的同时也增加了代码阅读的难度。
1. Lambda的格式
正常情况下我们定义一个函数,样式如下:
int func(int iX, int iY)
{
return iX + iY;
}
而Lamda是匿名函数,故没有函数名,经过转换变成下面的样子:
[] (int iX,int iY) {return iX+iY;}
上面的表达式确定了三点: 匿名函数名,参数,返回值。此时,假设我们需要引用外部的变量,则需要添加捕获子句:
int oX =3;
int oY =4;
//调用方式1
auto autofun = [oX,oY](int iX,int iY){return iX+iY+oX+oY;};
autofun(1,2);
//调用方式2
[oX,oY](int iX,int iY){return iX+iY+oX+oY;}(1,2);
如果想要在匿名函数体内改变外部的变量呢?那就需要捕获引用:
//第一种写法,按每个参数需要添加引用
[&oX,oY](int iX,int iY)
{
oX++;
//oY++;//oY未添加&,报错
return iX+iY+oX+oY;
};
//第二种写法,全部添加引用
[&](int iX,int iY)
{
oX++;
oY++;//正常
return iX+iY+oX+oY;
};
//第三种写法:全部添加引用,如果是传值的单独列出来(即例外)
[&,oY](int iX,int iY)
{
oX++;
//oY++;//oY单独列出来是传值,不可修改,报错
return iX+iY+oX+oY;
};
类似的,&表示捕获引用,则=表示捕获值,使用方法一致。
2.规范
可变规范mutable:注意如果捕获的是引用可正常修改,如果捕获的是值则修改的是副本!
[oX,&oY] (int iX,int iY) mutable
{
oX++; //oX并没有被修改,此处是oX副本
oY++; //oY是捕获的引用,可正常修改
return iX+iY+oX+oY;
};
异常规范noexcept :指示不会发生任何异常(G++高版本似乎不支持)
[] () noexcept
{
throw -1; //G++ 8.1依然会抛异常结束应用
};
3. 注意点
- 捕获模式分为[&]引用和[=]两种。单独的符号表示全局模式,例外的参数要列出来
- 引用能被修改,而值不能
- 捕获列表与写的顺序无关,[a, b]与[b,a]等效
- 捕获不能重复参数,例如[a,a]是错误的
- 函数体的返回就是返回值,可以为空
- 同一类型的捕获不需要列出来,只列例外,如[&,&oY]或[=,oY]某些编译器可能报错
总结
Lamda与普通的函数定义相比,使用上更加简洁和高效,特别是对于一些排序、比较等的处理,但对于有独立功能的方法,还是使用函数定义更利于代码的维护。