【C++】lambda表达式

lambda表达式语法

[capture-list] (parameters) mutable -> return-type {statement}

各部分说明

  • 【capture-list】:捕捉列表,编译器通过[]来判断接下来的代码是否是lambda表达式,捕捉列表可以捕捉上下文中的变量宫lambda表达式使用
  • (parameters):参数列表。与普通函数的参数列表一致。如果不需要参数传递,则可以连同()一起省略
  • mutable:用来取消捕捉列表中拷贝对象的常属性,使用该修饰符时,参数列表不可以省略
  • ->returntype:用来声明函数的返回值类型。没有返回值是此部分可以被省略。返回值类型明确的情况下,也可以省略,由编译器堆返回值类型进行推导
  • {statement}:函数体。在该函数内部除了可以使用参数列表中的参数外,还可以使用所有捕获到的变量

注意
  在lambda表达式中,只有捕捉列表和函数体是不可以省略外,其他部分都可以被省略,由此,在C++11中最简单的lambda表达式就是:[]{},该表达式不能做任何事情

在这里插入图片描述
以上就是使用lambda表达式的一个例子

捕捉列表和mutable说明

  捕捉列表描述了上下文中哪些数据可以被lambda表达式使用
例如:

#include<iostream>
int main()
{
	int a = 2, b = 3;
	auto swap = [a, b]()
		{
			int t = a;
			a = b;
			b = t;
		};
	swap();
	std::cout << a << ' ' << b << std::endl;
	return 0;
}

以上代码中,捕捉列表捕捉了同在main函数中的变量a和变量b,并试图将它们进行交换
在这里插入图片描述
  当运行时出现以上报错,这是因为捕捉列表捕捉的变量实际上是原变量的拷贝,并且这个拷贝对象是被const所修饰的,当对这个对象进行修改时就会报错。若要修改拷贝的常属性,需要用到mutable
  此时代码被修改为

#include<iostream>
int main()
{
	int a = 2, b = 3;
	auto swap = [a, b]()mutable
		{
			int t = a;
			a = b;
			b = t;
		};
	swap();
	std::cout << a << ' ' << b << std::endl;
	return 0;
}

在这里插入图片描述
因为lambda表达式捕捉列表中的变量是原变量的拷贝,所以对于拷贝变量的修改无法影响到原变量,如果想要修改原变量,则需要传递原变量的引用

#include<iostream>
int main()
{
	int a = 2, b = 3;
	auto swap = [&a, &b]()
		{
			int t = a;
			a = b;
			b = t;
		};
	swap();
	std::cout << a << ' ' << b << std::endl;
	return 0;
}

在这里插入图片描述
关于捕捉列表的说明

  • [var] :用值传递的方式捕捉变量
  • [=] : 用值传递的方式捕捉父作用域中的所有变量
  • [&var] : 用引用传递的方式捕捉变量
  • [&] : 用引用传递的方式捕捉父作用域中的所有变量
  • [this] : 表示值传递的方式捕捉当前的this指针
  • 父作用域指的是包含lambda表达式的语句块
  • 语法上捕捉列表可以由多个捕捉项构成,并用逗号分隔
    例如:[=,&a,&b] 表示用引用传递的方式捕捉变量a和变量b,值传递的方式捕捉其他变量
    [&,a,this] :用值传递的方式捕捉a变量和this指针,引用传递的方式捕捉其他变量
  • 捕捉列表不允许变量重复传递
    例如:[=,a],=代表已经用值传递的方式捕捉了所有变量,再用值传递的方式捕捉a就会造成重复
  • 在块作用域以外的lambda表达式捕捉列表必须为空

函数对象与lambda表达式

函数对象,又被称为仿函数,就是在类中重载了operator()运算符的类对象

class Greater
{
public:
	bool operator()(int a, int b)
	{
		return a > b;
	}
};

int main()
{
	Greater g1;
	g1(1, 2);//函数对象

	//lambda表达式
	auto g2 = [](int a, int b)->bool { return a > b; };
	g2(1, 2);

	return 0;
}

从使用方式上来看,这两者便没有什么差别
我们可以从汇编的角度来看看
在这里插入图片描述
在这里插入图片描述
  在函数对象的汇编中,我们可以看到,当我们运行到g1(1,2)时,就会跳转到Greater类中已经重载好的operator()函数中
  在lambda表达式中,当运行到g2(1,2)时,程序也会跳转到一个类中的operator()中,(这个类的名字是随机生成的,在不同编译器中命名规则也不同),这就可以印证了C++中lambda表达式其实是用仿函数实现的:生成一个名字随机的类,并重载类中的operator()运算符。
  另外,这个类的默认构造是已经被禁用了的,但是拷贝构造并没有被禁用
在这里插入图片描述
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值