Last Updated: 2023-12-25 07:47:28 Monday
-- TOC --
一段小巧玲珑的代码,不需要专门定义,常常作为某些库函数接口的参数,随用随写,用后即焚。这就是lambda表达式给人的印象。我觉得还可以说,因为lambda表达式的存在,我们可以实现在C++的函数内,定义nested函数。
Lambda Expressions. Constructs a closure: an
unnamed function object
capable of capturing variables in scope. 匿名函数对象。
#include <iostream>
using namespace std;
int main(){
int x { 5 };
auto f { [=](int a){return a+1+x;} };
cout << f(1) << f(2) << f(3) << endl;
return 0;
}
f就是一个lambda函数对象,定义在main内,执行这段代码,输出:789。
C++11开始引入lambda函数,其基本格式如下:
[captures](params) specs { body }
[captures],定义如何捕获上下文中的变量
[]
,什么也不捕获,无法lambda函数体内使用上下文中的变量。[=]
,按copy的方式捕获所有变量,包括成员函数隐藏的this指针。[&]
,按ref的方式捕获所有变量。[=,&a]
,变量a使用ref的方式来捕获,其它变量按copy的方式捕获。可以有多个像a这样的变量,比如[=,&a,&b,&c]
。当全部捕获用=
时,单独捕获就必须是&
。[&,a]
,变量a使用copy的方式来捕获,其它变量按ref的方式捕获。可以有多个像a这样的变量,比如[&,a,b,c]
。当全部捕获用&
时,单独捕获就必须是=
(=号省略了)。[a,&b]
,以copy的方式捕获a,以ref的方式捕获b,全部采用单独捕获,我比较喜欢。[this]
,在成员函数中捕获this指针,以copy的方式。(params),lambda接口参数
定义lambda函数接口的入参,与普通函数接口一样定义。注意params里面的变量名称,不要与captures中的变量冲突。params is optional
,如果不写,有无空的()
都可以,都表示没有任何入参,个人建议写上空括号看起来比较顺眼。参数列表中可以使用auto
,
specs
这部分有一些specifiers可以用,我现在只知道trailing-return-type
可以写在这里。
trailing-return-type
:写成-> type
这样的literal,但一般可以省略掉,由编译器根据body内的return语句来推导。{body},lambda函数体
函数体,定义功能的地方,就是一些C++的statements。
测试代码:
#include <iostream>
#include <vector>
#include <string>
#include <type_traits>
using namespace std;
int main(){
vector<int> a {1,2,3,4,5,6,7,8,9};
vector<string> b {"11","22","33","aa","bb"};
auto f {
[](auto &x){
using st = typename remove_reference_t<decltype(x)>::size_type;
for(st i{}; i<x.size(); ++i)
cout << x[i] << "..";
cout << endl;
}
};
f(a);
f(b);
return 0;
}
输出:
1..2..3..4..5..6..7..8..9..
11..22..33..aa..bb..
本文链接:https://cs.pynote.net/sf/c/cpp/202309285/
-- EOF --
-- MORE --