C++11 lambda

时间:2021-06-12 00:37:42


 Lambda 介绍

   Lambda 函数也叫匿名函数, 是C++ 11中新增的特性;

1. Lambda函数的好处

 如果你的代码里面存在大量的小函数,而这些函数一般只被调用一次,那么将他们重构成 lambda 表达式。

Lambda函数使代码变得更加紧凑、更加结构化和更富有表现力;

lambda在c++作用主要是作为内嵌函数,逻辑更加清楚,代码可读性更好;

例:

void main()
{
thread t1([]() {
printf("hello...");
});
t1.join();

}

2. C++11 的 lambda 表达式规范如下:

C++11 lambda

此图显示了 lambda 的组成部分:

  1. capture 子句(在 C++ 规范中也称为 Lambda 引导。)
  2. 参数列表(可选)。 (也称为 Lambda 声明符)
  3. mutable 规范(可选)。
  4. exception-specification(可选)。
  5. trailing-return-type(可选)。
  6. Lambda 体。

具体见:

​C++ 中的 Lambda 表达式 | Microsoft Learn​

Lambda 表达式的定义形式如下:

[外部变量访问方式说明符] (参数表) -> 返回值类型
{
语句块
}

 example

[=] (int x, int y) -> bool {return x%10 < y%10; }

Lambda捕获列表

Lambda表达式与普通函数最大的区别是,除了可以使用参数以外,Lambda函数还可以通过捕获列表访问一些上下文中的数据;

语法上,在“​​[]​​”包括起来的是捕获列表

捕获列表由多个捕获项组成,并以逗号分隔。捕获列表有以下几种形式:

​[]​​表示不捕获任何变量

​[var]​​​表示值传递方式捕获变量​​var​

int num = 100;
auto function = ([num]{
std::cout << num << std::endl;
}
);

 [&var]表示引用传递捕捉变量var  (可修改值)

​[=]​​表示值传递方式捕获所有父作用域的变量(包括​​this​​)

​[=, &a, &b]​​​表示以引用传递的方式捕捉变量​​a​​​和​​b​​,以值传递方式捕捉其它所有变量

​[&, a, this]​​​表示以值传递的方式捕捉变量​​a​​​和​​this​​,引用传递方式捕捉其它所有变量。

不过值得注意的是,捕捉列表不允许变量重复传递。下面一些例子就是典型的重复,会导致编译时期的错误。例如:

[=,a]这里已经以值传递方式捕捉了所有变量,但是重复捕捉a了,会报错的;
[&,&this]这里&已经以引用传递方式捕捉了所有变量,再捕捉this也是一种重复。

Lambda参数列表

Lambda还可以接受输入参数。参数列表是可选的, 类似于函数的参数列表

auto function = [] (int a, int b){
return a+ b;
};

function(100, 200);

可变规格mutable

默认情况下Lambda函数总是一个​​const​​​函数,​​mutable​​可以取消其常量性。在使用该修饰符时,参数列表不可省略(即使参数为空)。

#include <iostream>
using namespace std;

int main()
{
int m = 5;
[&] (int a) mutable { m += a; }(6); // a=6;
cout << m << endl;
}

输出 11;

返回类型

Lambda表达式的返回类型会自动推导。除非你指定了返回类型,否则不必使用关键字

auto x1 = [](int i){ return i; };

Lambda表达式的缺点

  • Lamdba表达式语法比较灵活,增加了阅读代码的难度
  • 对于函数复用无能为力

Lamdba 表达式应用于STL算法库 

#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int a[4] = { 1, 2, 3, 4 };
int total = 0;
for_each(a, a + 4, [&](int & x) { total += x; cout << total << endl; });
cout << total << endl; //输出 10

return 0;
}