DiuR21Laonnu

lambda - 匿名函数

2017/09/26

前言

​ Github上大量的C++代码运用了lambda表达式,因为之前对该特性的忽略甚至说是误解导致没有认真的深入学习lambda表达式。对代码的学习产生了阻碍。

​ 本文是对C++ 下 lambda表达式的介绍以及总结

Lambda表达式

​ Lambda 函数又称匿名函数,亦即是为没有名字的函数。通常用于封装传递给算法或异步方法的少量代码行。

1
2
3
4
5
6
7
8
9
10
11
#include <algorithm>
#include <cmath>
void abssort(float* x, unsigned n) {
std::sort(x, x + n,
// Lambda expression begins
[](float a, float b) {
return (std::abs(a) < std::abs(b));
} // end of lambda expression
);
}

pic1

  1. Capture 子句(在 C++ 规范中也称为 lambda 引导。)
  2. 参数列表(可选)。 (也称为 lambda 声明符)
  3. 可变规范(可选)。
  4. 异常规范(可选)。
  5. 尾随返回类型(可选)。
  6. “lambda 体”

Capture子句

#### Capture子句功能演示
1
2
3
4
5
6
7
8
9
10
int main()
{
{
int a = 1;
auto lFuc = [=](){ cout << a << endl;};
lFuc();
}
}
//results:
1

​ 对比程序

1
2
3
4
5
6
7
8
9
10
11
int main()
{
{
int a = 1;
auto lFuc = [=](){ cout << a << endl;};
lFuc();
}
auto lFuc = [=]() { cout << a << endl;};
lFuc();
}
//error

观察上述两段代码,Capture子句( C++规范中也被称为 lambda引导)指导了lambda语句获取变量的方式。而Capture子句获取变量的范围是有作用域统治的。

捕获变量的一些规则

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[] //不捕获变量
[=] //所有值,按值捕获
[&] //所有值,按引用捕获
truct S { void f(int i); };
void S::f(int i) {
[&, i]{}; // OK
[&, &i]{}; // ERROR: i preceded by & when & is the default
[=, this]{}; // ERROR: this when = is the default
[i, i]{}; // ERROR: i repeated
}
//默认使用&,则不可对于具体变量使用&引用捕获。

使用capture子句应注意的细则

  • 引用捕获可用于修改外部变量,而值捕获却不能实现此操作。 (mutable允许修改副本,而不能修改原始项。)
  • 引用捕获会反映外部变量的更新,而值捕获却不会反映。
  • 引用捕获引入生存期依赖项,而值捕获却没有生存期依赖项。 当 lambda 以异步方式运行时,这一点尤其重要。 如果在异步 lambda 中通过引用捕获本地变量,该本地变量将很可能在 lambda 运行时消失,从而导致运行时访问冲突。

####参数列表

​ lambda可以接受输入参数。参数列表是可选的。类似于函数的参数列表

1
2
3
4
5
6
7
8
9
10
11
int main()
{
auto y = [] (int first, int second)
{
return first + second;
};
cout<<y(1,2)<<endl;
}
//results
//3

可变规范(可选)

​ 通常,lambda 的函数调用操作是 const-by-value的,不会生成可变的数据成员,但使用 mutable 关键字可以改变这个情况。使用 mutable 关键字可以在lambda 表达式的主体内修改值变量。

1
2
3
4
5
6
7
8
9
int i = 1;
auto y = [i] (int first, int second)
mutable//若不添加mutable关键字,则编译错误
{
i++;
};
cout<<i<<endl;
//result
//i = 1;

异常规范(可选)

​ 暂不明白

返回类型

​ lambda表达式自动推导饭回来行。除非指定尾随返回类型。指定尾随类型类似于普通方法或函数的返回类型部分。但是,返回类型必须在参数列表后方,必须要指定尾随类型前使用关键字 ->

lambda初步学习完毕= =…