C&C++学习笔记(5)——Lambda表达式

Lambda是C++11中的新概念,使用也是十分方便。

本文仅供个人记录和复习,不用于其他用途

什么是Lambda表达式

C++11中新增了Lambda表达式,用于定义并创建匿名函数对象,简化编程工作。Lambda表达式就相当于包含共有operator()的匿名结构(或类)。

1
for_each(vecIntegers.begin(), vecIntegers.end(), [](int &Element){cout << element << ' ';});

那么类似于如下表达式:

[](int &Element){cout << element << ' ';}

就会展开为如下结构:

1
2
3
4
5
6
7
struct NoName
{
void operator () (const int &element) const
{
cout << element << ' ';
}
};

Lambda表达式的定义

Lambda表达式必须以[]打头,然后是一个参数列表,这个列表和提供给operator()的参数列表是相同的。

一元函数对应的Lambda表达式

形式如下:

1
2
[](Type paramName) {// ...;}
[](Type &paramName) {// ...;}

一元谓词对应的Lambda表达式

形式如下:

1
[](int &Num) {return ((Num % 2) == 0);}

二元函数对应的Lambda表达式

形式如下:

1
[...](Type1 &param1Name, Type2 &param2Name) {// ...;}

二元谓词对应的Lambda表达式

形式如下:

1
[...](Type1 &param1Name, Type2 &param2Name) {// ...;}

通过捕获列表接受状态变量的Lambda表达式

在上面的这个Lambda表达式中,我们接受用户传入的一个数值,如果能够被2整除,那么就返回true。但是呢,如果用户需要其他的数时,这个就不方便了。因此,我们需要让Lambda表达式接受一个状态,在这里就是除数。

1
2
3
int Divisor = 2;
auto iElement = find_if(vecIntegers.begin(), vecIntegers.end(), [Divisor](int dividend) {return (dividend % Divisor) == 0;});

这样的话,就可以传入不同的参数,用户可以自定义除数。

Lambda表达式的通用语法

这里介绍一下可以使用的状态变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 接受两个状态变量
[StateVar1, StateVar2](Type &param) {// ...;}
// 添加关键字mutable,可以修改[]中的变量(仅仅只是修改拷贝,原本的变量值不变)
[StateVar1, StateVar2](Type &param) mutable {// ...;}
// 也可以传入拷贝,这样能够使得修改变量在外部也能生效
[&StateVar1, &StateVar2](Type &param) mutable {// ...;}
// 可以接受多个输入参数
[StateVar1, StateVar2](Type1 &var1, Type2 &var2) {// ...;}
// 如果要想编译器明确地指出返回的类型,那么就可以使用->
[StateVar1, StateVar2](Type1 &var1, Type2 &var2) -> ReturnType {return (value or expression);}
// 当然,{}中可以包含多条语句,但是必须明确指出返回类型
[StateVar1, StateVar2](Type1 &var1, Type2 &var2) -> ReturnType
{Statement 1; Statement 2; return (value or expression);}

总的来说,Lambda表达式更简洁更方便,不需要去定义结构或者类。

注意事项

  • 没有使用mutable关键字时,不能够修改捕获列表中指定的状态变量。
  • 编写Lambda表达式时,不要忘记使用const对参数进行限定。
  • 包含多条语句时,必须指定返回类型
  • 不要用很长的Lambda表达式,应该使用函数对象