C++:Lambda表达式举例讲解
- Lamble表达式简单使用。
- 表达式中变量的捕获。
- 修改值传递捕获的值。
- 参数的泛型
一、如何使用Lambda表达式
Lambda表达式声明格式如下(不必每一个表达式均完整包含所有项):
[捕获列表] (形参列表) mutable 异常设定 -> 返回类型 { 函数主体; };
// =====================================
// 例一
int a = 10;
auto x = [a]() {cout << a << endl;}; // 声明
x(); // 调用
// 现象
// 10
// =====================================
// 例二
auto x = [] {cout << "abc" << endl;};
x();
// 现象
// abc
// =====================================
// 例三
int a = 10;
auto x = [](int a) {cout << a << endl;};
x();
// 现象
// 10
// =====================================
// 例四
int a = 10, b = 20;
auto x = [](int a, int b) -> bool {return a < b;};
cout << x(a, b) << endl;
// 现象
// 1 因为a小于b,所以返回1
- 捕获列表:将表达式外部的变量捕获,即可直接使用表达式的外部变量,如例一。若不捕获任何变量,也不可省略[],因为[]还有一个作用是引出表达式,实际使用如例二。
- 形参列表:如同普通函数的形参一般,声明时写明,在调用时将实参传入。若无形参可不写,如例二。在例一中
()
可省略不写。调用方式如例三。 - multable:用来说明是否可以修改捕获的变量。下一节详细讨论。
- 异常设定。
- 返回类型,用来指定返回值的类型,注意,此处的返回值与
Lambda
表达式返回值毫无关系。此处的返回值决定调用表达式时返回的类型。并且返回值类型可自动推导,故写不写均可,建议写一下。实例见例四。 - 函数主体:与普通函数主题相同,注意在每一句末尾加
;
。 Lambda
表达式返回值:可通过接收表达式的返回值来调用表达式,勿将此返回值与前文所言的搞混。而每一个表达式都会返回独有的类型,此类型无法直接写出,故使用auto
自动推导。
二、Lambda表达式使用细节
此节将深入探讨表达式的一些使用技巧和细节。
2.1 变量的捕获
表达式通过[]
来对外部变量进行捕获。捕获外部变量不止只有在[]
写出变量名这一种方式,详细使用方式见下表。
捕获方式 | 功能 |
---|---|
[变量名1, …] | 以变量名方式捕获变量。 |
[=] | 以值传递的方式,获取外部所有变量。 |
[&] | 以引用的方式,获取所有外部变量。 |
[this] | 捕获this指针。 |
[=, &x] | 除了变量x以引用方式捕获,其余用值方式。 |
[&, x] | 除了变量x以值方式捕获,其余用引用方式。 |
若使用引用捕获,在表达式中修改变量值,自然会影响外部值,如下面例子。
int a = 10;
auto x = [&]{a = 20};
x();
cout << a << endl;
// 现象
// 20
若使用值传递,则不可在表达式中改变捕获的值,修改会报错,除非使用multable
。
2.2 修改值传递捕获的值
如果在表达式中使用mutable
,则可以修改值传递捕获来的数据,见如下例子。
int a = 10;
auto x = [a]()mutable{a = 20;}; // 即使没有参数,()括号也不可省略
x();
cout << a << endl;
// 现象
// 10
由于是值传递,故即使表达式内改变了值,也不影响外面的值。
2.3 参数泛型
普通函数的泛型中,需要写一个类似于template<class T>
的模板,而在表达式中,并不需要如此。表达式的泛型是通过auto
关键字实现的。
int a = 10;
double b = 2.5;
auto x = [](auto& i) { i *= 2; }; // 将数乘2
x(a);
x(b);
cout << a << endl;
cout << b << endl;
// 现象
// 20
// 5
注意,函数中是不可用auto
关键字做泛型的。
好了,本文到此结束了,若有疏漏之处,望前辈们不吝赐教。