声明
Lambda表达式完整的声明格式如下:
[capture list] (params list) mutable exception-> return type { function body }
各项具体含义如下
- capture list:捕获外部变量列表
- params list:形参列表
- mutable指示符:用来说用是否可以修改捕获的变量
- exception:异常设定
- return type:返回类型
- function body:函数体
但是并不是所有的项都必须写全,可以省略一些不需要的项,一般很少写exception。 比如:
- 如果不能修改捕获外部变量的值,则不需要写mutable指示符
[capture list] (params list) -> return type { function body }
[](int a)->bool {return a>1;}
-> return type 可以不写。如果function body里边有return,则返回return的返回值类型,如果没有return,则返回void
[capture list] (params list){ function body }
[](int a){return a>1;}
- 如果没有参数,则params list可以不写
[capture list]{ function body }
int a = 2;
[a]{return a>1;}
捕获外部变量
1、值捕获 值捕获和参数传递中的值传递类似,被捕获的变量的值在Lambda表达式创建时通过值拷贝的方式传入,因此随后对该变量的修改不会影响影响Lambda表达式中的值。 比如上边最后一个例子。
int a = 2;
auto m = [a]{return a>1;};
a=0;
cout << m() << endl;
2、引用捕获 使用引用捕获一个外部变量,只需要在捕获列表变量前面加上一个引用说明符& 。
int a = 2;
auto m = [&a]{return a>1;};
a=0;
cout << m() << endl;
3、隐式捕获 上面的值捕获和引用捕获都需要我们在捕获列表中显示列出Lambda表达式中使用的外部变量。除此之外,我们还可以让编译器根据函数体中的代码来推断需要捕获哪些变量,这种方式称之为隐式捕获。隐式捕获有两种方式,分别是[=] 和[&] 。[=] 表示以值捕获的方式捕获外部变量,[&] 表示以引用捕获的方式捕获外部变量。
int a = 2;
auto m = [=]{return a>1;};
a=0;
cout << m() << endl;
a = 2;
auto n = [&a]{return a>1;};
a=0;
cout << n() << endl;
总结:
捕获形式 | 说明 |
---|
[] | 不捕获任何外部变量 | [变量名, …] | 默认以值得形式捕获指定的多个外部变量(用逗号分隔),如果引用捕获,需要显示声明(使用&说明符) | [this] | 以引用的形式捕获this指针 | [*this] | 以值的形式捕获this指针 | [=] | 以值的形式捕获所有外部变量 | [&] | 以引用形式捕获所有外部变量 | [=, &x] | 变量x以引用形式捕获,其余变量以传值形式捕获 | [&, x] | 变量x以值的形式捕获,其余变量以引用形式捕获 |
修改捕获变量
前面我们提到过,在Lambda表达式中,如果以传值方式捕获外部变量,则函数体中不能修改该外部变量,否则会引发编译错误。那么有没有办法可以修改值捕获的外部变量呢?这是就需要使用mutable关键字,该关键字用以说明表达式体内的代码可以修改值捕获的变量,比如:
int a = 2;
auto m = [a] ()mutable {
a = -1;
return a>1;
};
cout << m() << endl;
表达式的参数
在Lambda表达式中传递参数还有一些限制,主要有以下几点:
- 参数列表中不能有默认参数
- 不支持可变参数
- 所有参数必须有参数名
推荐阅读
C++ lambda表达式与函数对象 基础篇:Lambda 表达式和函数对象
|