您的位置:首页 > 编程语言 > C语言/C++

C++ lambda表达式

2020-07-30 22:01 281 查看

与函数类似,lambda表达式也是一种可调用对象,但其可以定义在函数内部。《C++ Primer》中提到一个lambda表达式表示一个可调用的代码单元,可以将其理解为一个未命名的内联函数。本笔记参考《C++ Primer》,主要对C++ lambda表达式的用法进行一个简单的记录。

用法简介

当需要一个实现简单功能的可调用对象时,使用lambda表达式可以使得代码更为简洁。在一些泛型算法中可以直接传入lambda表达式自定义规则,比如sort第三个参数直接写个lambda表达式指定排序规则。

lambda表达式的形式如下:

[capture list](parameter list) -> return type {function body}

[捕获列表](参数列表) -> 返回类型 {函数体}

捕获列表用来放置在lambda表达式所在函数中定义的需要传入lambda表达式的局部变量。其余部分的含义与函数定义中对应的部分相同。不过lamdba必须使用尾置返回。lambda表达式中,参数列表和返回类型可以省略,捕获列表(尽管可能为空)和函数体必须存在。调用lambda表达式的方法也与调用普通函数一样,使用调用运算符

()
即可。

简单示例

简单的lambda表达式及调用示例如下,该示例捕获列表为空,没有参数列表和返回类型,函数体也仅仅是返回一个字符串。

auto fun = [] { return "Hello world!"; };
cout << fun() << endl;//输出Hello world!

参数传递

lambda表达式传递参数的方式也与函数类似,使用给定实参初始化形参,通常实参和形参类型必须匹配。下面给出一个示例。

auto fun = [](const string &s1, const string & s2) { return s1 + ' ' + s2; };
string s1 = "Hello";
string s2 = "world";
cout << fun(s1,s2) << endl;//输出Hello world

捕获列表的使用

通过捕获列表,我们可以在lambda表达式中使用lambda表达式所在函数中定义的局部变量。

值捕获和引用捕获

采用值捕获,被捕获的变量的值是在lambda创建时拷贝。下面的示例中,变量a在lambda创建时被捕获,完成了值的拷贝,因此当a的值改变后,再调用lambda发现并不起作用。

int a = 1;
auto fun = [a](int b) { return a + b; };
int b = 1;
cout << a << ' ' << b << endl;//输出1 1
cout << fun(b) << endl;//输出2
a += 1;
cout << a << ' ' << b << endl;//输出2 1
cout << fun(b) << endl;//输出2

引用捕获的示例如下

int a = 1;
auto fun = [&a](int b) { return a + b; };
int b = 1;
cout << a << ' ' << b << endl;//输出1 1
cout << fun(b) << endl;//输出2
a += 1;
cout << a << ' ' << b << endl;//输出2 1
cout << fun(b) << endl;//输出3

隐式捕获

使用隐式捕获,就可以不显式列出要在lambda表达式要捕获的变量,取而代之的是让编译器通过lambda表达式中的代码来推断使用的变量。在捕获列表中写个

=
指示使用引用捕获方式,写个
&
指示使用引用捕获方式。

int a = 1;
auto fun = [=](int b) { return a + b; };//[]中写个=,使用值捕获方式
int b = 1;
cout << a << ' ' << b << endl;//输出1 1
cout << fun(b) << endl;//输出2
a += 1;
cout << a << ' ' << b << endl;//输出2 1
cout << fun(b) << endl;//输出2
int a = 1;
auto fun = [&](int b) { return a + b; };//[]中写个&,使用引用捕获方式
int b = 1;
cout << a << ' ' << b << endl;//输出1 1
cout << fun(b) << endl;//输出2
a += 1;
cout << a << ' ' << b << endl;//输出2 1
cout << fun(b) << endl;//输出3

可以混用显式捕获和隐式捕获。不过若隐式部分使用值捕获方式,则显式部分就不能用值捕获方式,反之,隐式部分使用引用捕获方式,则显式部分就不能用引用捕获方式。

int a = 1;
int b = 1;
auto fun = [&, b](int c) { return a + b + c; };
int c = 1;
cout << fun(b) << endl;//输出3

显式捕获和隐式捕获用同一种方式提示错误:


当然,要是不用隐式捕获,捕获列表中各变量的捕获方式就随便写。

尾声:就简单记录这么多,一般我自己也很少用到复杂的情况。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: