C++11:Lambda表达式
Posted 木大白易
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++11:Lambda表达式相关的知识,希望对你有一定的参考价值。
声明
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;//这里输出为1
2、引用捕获
使用引用捕获一个外部变量,只需要在捕获列表变量前面加上一个引用说明符&
。
int a = 2;
auto m = [&a]{return a>1;};
a=0;
cout << m() << endl;//这里输出为0
3、隐式捕获
上面的值捕获和引用捕获都需要我们在捕获列表中显示列出Lambda表达式中使用的外部变量。除此之外,我们还可以让编译器根据函数体中的代码来推断需要捕获哪些变量,这种方式称之为隐式捕获。隐式捕获有两种方式,分别是[=]
和[&]
。[=]
表示以值捕获的方式捕获外部变量,[&]
表示以引用捕获的方式捕获外部变量。
int a = 2;
auto m = [=]{return a>1;};
a=0;
cout << m() << endl;//这里输出为1
a = 2;
auto n = [&a]{return a>1;};
a=0;
cout << n() << endl;//这里输出为0
总结:
捕获形式 | 说明 |
---|---|
[] | 不捕获任何外部变量 |
[变量名, …] | 默认以值得形式捕获指定的多个外部变量(用逗号分隔),如果引用捕获,需要显示声明(使用&说明符) |
[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;//这里输出为0
表达式的参数
在Lambda表达式中传递参数还有一些限制,主要有以下几点:
- 参数列表中不能有默认参数
- 不支持可变参数
- 所有参数必须有参数名
推荐阅读
以上是关于C++11:Lambda表达式的主要内容,如果未能解决你的问题,请参考以下文章