C++ Lambda表达式

参考:
C++ 11 Lambda表达式
C++之Lambda表达式

1、Lambda表达式写法格式

[捕获变量列表] (输入参数列表) mutable 或 exception 声明 -> 返回值类型 {函数体}

几种省略写法:

[] (输入参数列表)-> 返回值类型 {函数体} // 捕获变量列表为空
[] (输入参数列表){函数体} // 自动推导返回值类型,没有return语句时返回类型为void
[]{函数体} // 捕获列表、输入参数均为空

2、Lambda的名称与执行

2.1为Lambda指定名称并执行

auto lambda_name = [](int a) { std::cout << a; };
lambda_name(1); // 执行Lambda
lambda_name(2);

lambda_name 为该Lambda的名称,相当于函数名。lambda_name 的实际类型随表达式的实现而定,取决于编译器使用是, 类型来跟踪Lambda。可以像使用常规函数那样使用有名称的Lambda。

2.2定义的同时执行Lambda

也可以在定义Lambda的同时执行它:

[](int a) { std::cout << a; }(1);

后面的(1)为实参列表。此时该Lambda并没有名称。

2.3不能在直接执行时给Lambda取名

auto lambda_name = [](int a) { std::cout << a; }(1); // 编译失败,error:“lambda_name”: 变量不能具有类型“void”

因为在直接执行Lambda时,前面的lambda_name会被认为是一个变量,用于接收Lambda的返回值,而非Lambda的名称。但此处Lambda的返回类型为void,变量不能为void类型,因此报错。
如果Lambda有返回值,则可定义变量来接收返回值:

auto m = [](int a) { return ++a; }(1); // 编译通过,m=2
auto n = [](int x) { return [](int y) { return y * 2; }(x)+6; }(5); // 编译通过,n=16

3、捕获变量列表

捕获变量列表用于列写需要捕获的外部变量名称。Lambda可以捕获其可见范围内的外部变量,在捕获列表[]中列写后即可在Lambda内部使用这些变量。

捕获的方式分为两种:值捕获 和 引用捕获

3.1值捕获

int a = 1;
auto lambda_name = [a]() { std::cout << a; };
lambda_name();

直接在[]中列写需要捕获的外部变量名称,类似于函数参数的值传递。拷贝的参数在函数内部是只读的,Lambda内部不能改变捕获得到的变量值。加上mutable关键字可以改变拷贝值,但不会影响原值:

int a = 1;
// auto lambda_name = [a](){ std::cout << ++a; }; // 编译失败,不能改变值捕获的变量值
auto lambda_name = [a]()mutable { std::cout << ++a; }; //编译成功,但不改变变量a的原始值
lambda_name();
std::cout << a; // a=1

也可以用=符号值捕获所有可见范围内的变量:

{
	int x = 10;
}
int a = 1;
int b = 2;
// auto lambda_name = [=]() { std::cout << x; }; // 编译失败,x不可见
auto lambda_name = [=]() { std::cout << a + b; }; // 编译成功,a、b可见
lambda_name();

3.2引用捕获

int a = 1;
auto lambda_name = [&a]() { std::cout << ++a; };
lambda_name();
std::cout << a; // a=2

在捕获的外部变量名称前面加&,类似于函数参数的引用传递。Lambda不需要mutable关键字就允许改变捕获得到的变量值,并且会改变该变量的原始值。
也可以用&符号引用捕获所有可见范围内的变量:

{
	int x = 10;
}
int a = 1;
int b = 2;
// auto lambda_name = [&]() { std::cout << x; }; // 编译失败,x不可见
auto lambda_name = [&]() { std::cout << (++a) + (++b); }; // 编译成功,a、b可见
lambda_name();
std::cout << a << b;

3.3混合捕获

值捕获与引用捕获可以混合使用:

int a = 1;
int b = 2;
auto lambda_name = [&a, b]() mutable { std::cout << (++a) + (++b); }; // 显示5
lambda_name();
std::cout << a << b; // a=2,b=2

或者:

int a = 1;
int b = 2;
int c = 3;
// auto lambda_name = [&a,=]() mutable { std::cout << (++a) + (++b) + (++c); }; // 编译失败,error:"=": 捕获默认只能出现在 lambda 捕获列表的开头
// auto lambda_name = [a,&]() mutable { std::cout << (++a) + (++b) + (++c); }; // 编译失败,error:"&": 捕获默认只能出现在 lambda 捕获列表的开头
auto lambda_name = [=,&a]() mutable { std::cout << (++a) + (++b) + (++c); }; // 编译成功,显示9
lambda_name();
std::cout << a << b << c; // a=2,b=2,c=3

除了变量a为引用捕获,其他变量均为值捕获。注意:=必须写在&a的前面。

4、Lambda用于STL

在C++11中,对于接受函数指针或函数对象的函数,可以使用Lambda作为其参数。

std::vector<int> buf = {1,4,3,5,2};
std::sort(buf.begin(), buf.end(), [](const int a, const int b) {return a < b; });
for (int x : buf) std::cout << x;

Lambda在此处代替了一般使用的函数指针,使代码更加简洁。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值