【C++新特性】 - lambda表达式

lambda表达式是C++11引入的新特性之一。

一个lambda表达式具有如下形式:

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

捕获列表是lambda所在函数中定义的局部变量(局部非static变量)的列表(通常为空,不能访问任何非static局部变量),lambda可以直接使用局部static变量和它所在函数之外声明的名字(比如cout)。参数列表、返回类型和函数体与普通函数一样,但是返回类型必须使用尾置返回方式,并且lambda不支持默认参数。

其中参数列表、可变/异常关键字和返回类型使可以缺省的,捕获列表和函数体是必须具备的。如果忽略返回类型,lambda将根据函数体中的代码推断返回类型。

auto f = [] { } // 最简的lambda表达式

当定义一个lambda表达式时,编译器会生成一个与lambda对应的新的(未命名的)类类型,所有捕获参数都在此类中有一个对应的数据成员。当向一个函数传递一个lambda或者使用auto定义一个使用lambda初始化的变量时,编译器会创建一个未命名的类类型,并生成一个此类型的对象,并且会完成数据成员的初始化。

上述例子,可以根据捕获的bool值来实现升序和降序的排序。如果对代码稍作修改,则结果将不一样:

由于sortFunc在初始化的时候便将isIncreaseOrder的值赋予了对应的成员变量,所以后续再修改局部变量isIncreaseOrder的值时,对lambda对象并无影响。

上述使用的捕获方式是值捕获。如果想要实现对应的功能,只需要将捕获列表方式修改为引用捕获,这样局部变量 isIncreaseOrder的值变化时,对定义的lambda对象也会产生影响:

lambda执行时可以直接修改引入传参的值,但是不能对值捕获参数进行修改(编译器会报错)。如果想要修改一个值捕获变量的值,可以加上mutable关键字。但是不论是值捕获还是引用捕获,如果变量定义为const,那么还是不能被修改。

除了在捕获列表中显示列出我们希望使用的来自所在函数的变量之外,还可以让编译器根据lambda函数体中的代码来推断我们要使用哪些变量。但是为了指示对变量的捕获方式,需要在捕获列表中写一个&或者=符号,告诉编译器我们期望的捕获方式,&表示引用捕获,=表示值捕获。如果两种方式都存在,则需要将不同捕获方式的变量及捕获方式显示的生命在&=符号后边,相同捕获方式的变量不需要再声明,否则会编译失败。

int main() {
	int m = 2;
//	auto lamb1 = []{ return m; }; // 编译错误,局部变量m没有被捕获(无法判断捕获类型)
//	auto lamb2 = [m]{ return ++m; }; // 编译错误,值捕获变量不能被修改
	auto lamb3 = [m]() mutable { return ++m; }; // 正常运行,加使用mutable关键字时,参数列表括号不能省,否则编译失败。
	cout << lamb3() << m << endl; // 输出32
	auto lamb4 = [&m] { return ++m; };
	cout << lamb4() << m << endl; // 输出33

	const int n = 3;
//	auto lamb5 = [n] () mutable { return ++n; }; // 编译错误,n为const类型,不能修改
//	auto lamb6 = [&n] { return ++n; }; // 编译错误,n为const类型,不能修改

	int a = 3;
	int b = 3;
	auto lamb7 = [=] { return a + b; }; // 正确,隐式值捕获
	auto lamb8 = [&] { return a + b; }; // 正确,隐式引用捕获
	auto lamb9 = [=, &b] { return a + b; }; // 正确,a值捕获,b引用捕获
	auto lamb10 = [&, b] { return a + b; }; // 正确,a引用捕获,b值捕获
//	auto lamb11 = [=, b] { return a + b; }; // 编译错误
//	auto lamb12 = [&, &b] { return a + b; }; // 编译错误

参考:C++之Lambda表达式 - 季末的天堂 - 博客园

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值