C++11 Lambda表达式

Lambda表达式

C++11的一大特性就是引入了Lambda表达式,并在后续的C++14进行了加强。
利用Lambda表达式,可以方便定义和创建匿名函数。
一个Lambda表达式表示一个可调用单元,我们可以将其理解为一个未命名的内联函数

Lambda语法定义

[capture list] (paramters list) mutable exception-> return type{function body}

其中——

  1. capture list,捕获外部变量列表;
  2. paramters list,形参列表;
  3. mutable,用来说明是否可以修改捕获的外部变量;
  4. exception,抛出异常;
  5. return type,返回类型;
  6. function body,函数体。

除此之外,还可以缺省部分声明构成不完整的Lambda表达式,常见的有以下几种——

序号 格式
1 [capture list] (params list) -> return type {function body}
2 [capture list] (params list) {function body}
3 [capture list] {function body}

其中——

  1. 格式1省略了mutable关键字和exception,声明的是一个const类型的表达式,这种表达式不能修改捕获列表中的值;
  2. 格式2 省略了返回类型return type,但是编译器可以根据functionbody中的return语句推断出Lambda表达式的返回类型,如果没有return语句,默认为void类型;
  3. 格式3中省略了参数列表,即无参的Lambda表达式。

举个使用Lambda表达式的例子——

#include
#include
#include
using namespace std;
int main(){
	vector<int> v{12,52,67,87,34,95,16,48};
	//使用格式3的Lambda表达式定义sort排序规则
	sort(v.begin(),v.end(),
		[](int&a,int&b){return a<b;});
	for(auto&elem:v){
		cout<<elem<<" ";
	}
	return 0;
}

在这里插入图片描述

Lambda捕获外部参数

Lambda表达式可以使用其可见范围内的外部变量,但必须明确声明。主要通过中括号[]来捕获外部变量,比如——

#include
using namespace std;
int main(){
	int a = 100;
	auto f = [a]{cout<<a<<endl;};
	f();// f相当于一个无参的函数调用
	return 0;
}

在这里插入图片描述

这种方式有别于传统的函数参数,增加了语言使用的灵活性。
Lambda表达式的外部变量捕获有4种方式:值捕获、引用捕获、隐式捕获和混合捕获

值捕获

值捕获与函数传参数相似,都是按值传递,外部变量的改变不会影响表达式已捕获变量的值——

#include
using namespace std;
int main(){
	int a = 100;
	auto f = [a]{cout<<a<<endl;};
	a = 200;// 此时改变a的值
	f();// 依旧输出100,而不是200
	return 0;
}

在这里插入图片描述

需要注意的是,捕获的外部变量是const的,无法修改。
如果需要修改,需添加mutable关键字,括号也不能省略,比如说——

#include
using namespace std;
int main(){
	int a = 100;
	auto f = [a]()mutable{cout<<++a<<endl;};
	a = 200;// 
	f();
	return 0;
}

在这里插入图片描述

引用捕获

顾名思义,就是捕获一个外部变量的引用,只需要在捕获的外部变量前面加上一个&即可——

#include
using namespace std;
int main(){
	int a = 100;
	auto f = [&a]{cout<<a<<endl;};
	a = 200;// 此时改变a的值
	f();// 输出200
	a = 300f();//输出300
	return 0;
}

在这里插入图片描述

隐式捕获

有时候,捕获的变量比较多的情况,一一书写变量名,可能就会很麻烦。
针对这种情况,Lambda提供了一种隐式捕获的方法,让编译器自行推断需要捕获哪些变量。
我们只需要定义捕获的方式是值捕获还是引用捕获,这就是隐式捕获

具体使用方法,举例如下——

#include
using namespace std;
int main(){
	int a = 100;
	int b = 200;
	int c = 300;
	int d = 400;
	auto f = [=]{
		cout<<"a = "<<a<<endl
		<<"b = "<<b<<endl
		<<"c = "<<c<<endl
		<<"d = "<<d <<endl;};// 值捕获 
	f();
	return 0;
}

在这里插入图片描述
只需要把=改成&,就变成引用捕获了,在此不再举例。

混合方式

Lambda还支持以上几种方式的混合使用,具体语法,总结如下——

序号 语法 作用
1 [] 不捕获任何外部变量
2 [args …] 默认是值捕获的方式,如果需要引用捕获,需要单独在变量名前加&
3 [this] 以值捕获的形式捕获this指针
4 [=] 以值捕获的形式捕获所有外部变量
5 [&] 以引用捕获的方式捕获所有的外部变量
6 [=,&x] 变量x以引用捕获,其余值捕获
7 [&,x] 变量x值捕获,其余引用捕获

Lambda参数列表

Lambda表达式的参数列表和函数的参数列表类似,但是又有所不同,具体表现为——

  1. 不支持默认参数列表
  2. 不支持可变参数列表
  3. 所有参数必须有参数名

相同之处在于,Lambda表达式的参数列表同样可以作为局部变量看待,能够覆盖同名的全局变量。

参考链接

  1. https://www.cnblogs.com/DswCnblog/p/5629165.html

你可能感兴趣的:(C/C++)