表达式语法

lambda表达式的语法格式是:[capture-list](parameters)->return-type {function body}

  • (parameters):参数列表。与普通的函数参数列表功能类似,如果不需要传参,则可以连同()一起省略。
  • ->return-type:return type是lambda函数的返回值类型。如果没有返回值,那么->return type这部分就可以省略,或者返回值类型明确的情况下,能由编译器自动推导返回类型出来,也能省略这部分。
  • {function body}:函数体。函数体的实现与普通函数完全一样,函数体内除了能使用参数列表外,还可以使用捕捉列表内的变量。函数体为空也必须写{}
  • [capture-list]:捕捉列表。该列表写在lambda表达式的开始位置,编译器根据[]来判断接下来的代码是否为lambda函数。捕捉列表能够捕捉上下文的变量,以供lambda函数内部使用,捕捉列表可以传值或传引用,捕捉列表就算为空也必须写[]

举几个栗子:

代码语言:javascript

AI代码解释

auto add = [](int x, int y){ return x + y; };

在这里插入图片描述

在这里插入图片描述

代码语言:javascript

AI代码解释

auto func = []
	{
		cout << "hello world" << endl;
	};

在这里插入图片描述

在这里插入图片描述

代码语言:javascript

AI代码解释

auto swap = [](int& a, int& b)
	{
		int tmp = a;
		a = b;
		b = tmp;
	};

在这里插入图片描述

在这里插入图片描述

非常好理解吧!

关于捕捉列表,还有一些使用的细节:

lambda表达式中默认只能使用参数列表中的变量或lambda内定义的,如果想使用外层作用域中的变量就需要进行捕捉。

  • 第一种方式是显式捕捉,在捕捉列表中可以显式传值捕捉和传引用捕捉,捕捉的多个变量用逗号分隔,比如[x, y, &z]表示x和y进行传值捕捉,lambda内部改变x和y不会改变原变量,而z是传引用捕捉,对z的改变会改变原变量。
  • 第二种捕捉方式是隐式捕捉,我们在[ ]中写一个 = 表示隐式值捕捉,写一个 & 表示隐式引用捕捉。这样我们的lambda的表达式中使用了哪些外部变量,编译器就会自动捕捉那些变量。
  • 第三种捕捉列表是混合捕获,可以组合使用隐式捕获和显式捕获,实现更精细的控制。[=, &x] 表示x进行引用捕捉,其余变量都为值捕捉;[&, x, y] 表示x和y进行值捕捉,其余变量进行引用捕捉。使用混合捕捉时,第一个元素必须是=或&,第一个是=时,后面的捕捉变量必须是引用捕捉;第一个是&时,后面的捕捉变量必须是值捕捉。

lambda表达式中如果在局部域时,可以捕捉到它之前定义的变量,不能捕捉静态局部变量和全局变量,因为这两种变量本来就不需要捕捉也能在内部直接使用,lambda表达式内部可以直接使用。lambda表达式如果定义在全局位置,捕捉列表必须为空。默认情况下,lambda捕捉列表是const属性的,也就是说传值捕捉来的对象不能被修改,在参数列表后加上修饰符mutable就可以取消其常性,但是修改还是改变的形参对象,不会影响实参。使用该修饰符后参数列表不能省略

更多推荐