许多编程语言支持 匿名函数的概念,这些函数有主体,但是,没有名称。
lambda 是使用匿名功能相关的编程方法。 lambda 隐式定义函数对象类和构造函数对象。选件类类型。
可以简单理解为:lambda是一种特殊的表达式,没有函数声明,却有实现主体。
lambdas表达式语法:
在图中的标注,如下所示:
-
lambda introducer (称为捕获子句在本主题后面)
-
lambda 参数声明列表 (称为 参数列表在本主题后面)
-
可变规范 (称为 可变规范在本主题后面)
-
异常规范 (称为 异常规范在本主题后面)
-
lambda 返回类型子句 (称为 返回类型在本主题后面)
-
复合语句 (称为 lambda 主体在本主题后面)
一、捕获子句
[&total, factor] //total按引用传递, factor按值传递
[&, factor]//除了factor按值传递,其他都按引用传递
[=, &total]//除了total按引用传递,其他都按值传递
二、参数列表
Lambda 表达式的参数列表与类似的参数列表的函数,但以下情况除外:
-
参数列表中不能有默认参数。
-
参数列表中不能有一个可变长度参数列表。
-
参数列表中不能有未命名的参数。
三、可变规范
实例:返回x+y
void main()
{
int x = 1;
int y = 2;
int z = [=]{return x + y;}();
}
四、异常规范
抛出异常:
int main() // C4297 expected
{
[]() throw() { throw 5; }();
}
五、返回类型
实例一:用引用传递才能修改lambdas范围内的变量的值,指定返回类型为int,如果不指定返回类型,主体只能有return语句。
void main()
{
int x = 1;
int y = 2;
int z = [&]() -> int{x++; return x + y;}();
}
实例二:换一种表达
参数列表中临时变量为a,赋值为4。
n按值传递,但是加上mutable修饰可变,但是在主体内++n修改了的是按值传递后的n,至于main函数中的n不改变值,
与引用传递不同。
int main()
{
int m = 0, n = 0;
[&, n] (int a) mutable { m = ++n + a; }(4);
cout << m << endl << n << endl;
}
六、lambdas主体
尽管 lambda 表达式可以只捕获自动存储持续时间的变量,您可以使用 lambda 表达式的正文中的静态存储持续时间的变量。
void main()
{
static int x = 1;
[](){return x++;}();
}
等效的是:
void main()
{
int x = 1;
[&](){return x++;}();
}
上述两个结果都是:2
但是与如下结果不同:
void main()
{
int x = 1;
[=]() mutable{return x++;}();
}
结果是1
就是因为一个是引用传值,一个是按值传递。
通过可以说已经有了对lambdas表达式基本的了解了:
引出几个algorithm中的函数来阐述lambdas表达式在容器中的应用,推广到以后自己的项目中能更高效:
一、for_each()函数:一般是遍历从 容器指定位置开始 到 容器指定位置结束的 功能
for_each(_InIt _First, _InIt _Last, _Fn1 _Func);
_InIt _First:容器指定位置开始
_InIt _Last:容器指定位置结束
_Fn1 _Func:lambdas表达式
void main()
{
vector<int> v(9, 1);
for_each(v.begin(), v.end(), [] (int n) {cout << n << endl;});
system("pause");
}
二、generate()函数
generate(_FwdIt _First, _FwdIt _Last, _Fn0 _Func);
_Fn0 _Func:能接收参数 与 _Fn1 _Func不同(不能接收参数)
generate改变已规定容器大小指定位置的值。
void main()
{
static int nextValue = 1;
vector<int> v(9, 1);
generate(v.begin(), v.end(), [] { return nextValue++; });
for_each(v.begin(), v.end(), [] (int n) {cout << n << endl;});
system("pause");
}
三、generate_n()函数:
可以规定生成大小,并对指定位置进行赋值
generate_n(_OutIt _Dest, _Diff _Count, _Fn0 _Func);
_OutIt _Dest:指定位置开始
_Diff _Count:指定生成大小
void main()
{
static int nextValue = 1;
vector<int> v(9,1);
generate_n(back_inserter(v), 9, [] { return nextValue++; });
for_each(v.begin(), v.end(), [](int n){cout << n << endl;});
system("pause");
}
其中back_inserter(v)函数:指的是在容器v的末尾的位置。不过要多包一个头文件<iterator>。