C++中的可调用对象大约有四种,分别是:函数、函数指针、重载了函数调用运算符的类、lambda表达式。其中lambda表达式就是今天本文的主题。
一个lambda表达式表示一个可调用的代码单元,可以理解为未命名的内联函数。一个lambda表达式具有返回类型、参数列表、函数体。
一般lambda表达式具有如下的形式:
[capture list] (parameter list) -> return type {function body}
其中:
capture list:捕获列表(lambda表达式所在的函数中定义的局部变量的列表)(通常为空)
parameter list :参数列表
return type:返回类型
function body:函数体
需要注意的是:一般时候,使用lambda表达式可以忽略lambda的参数列表和返回类型(原因下面再说)。
例子1:
void func_1()
{
int a=1;
auto func_lambda_1=[] (const int i) {cout<<i<<" "<<endl;}; //创建一个lambda表达式
func_lambda_1(a); //调用func_lambda_1,传入参数a;
}
例子2:
void_func_2()
{
int a=1;
auto func_lambda_2=[a] () {const<<a<<" "<<endl;}; //使用捕获列表,捕获函数func_2的局部变量a,
a=10;
func_lambda_2(); //调用func_lambda_2;结果为1;
}
注意:lambda表达式捕获方式有两种,分别是值捕获和引用捕获。func_lambda_2是值捕获。采用拷贝的方式传入lambda表达式,与参数不同的是,被捕获的变量在lambda创建时拷贝变量,而不是在调用时拷贝变量。
例子3:
void func_3()
{
int a=1;
auto func_lambda_3=[&a] () {const<<a<<" "<<endl;}; //使用引用捕获,
a=10; //改变a的值
func_lambda_3(); /调用func_lambda_3,结果为10;
}
注意:采用引用捕获时必须保证在lambda执行时被捕获的变量是存在的。若一个函数返回一个lambda表达式,lambda引用函数的局部变量,函数结束时局部变量被清除,而返回的lambda对象还使用该变量,此时会产生错误。
例子3:
void func_3()
{
int a=1; //局部变量
auto func_lambda_3=[a] () mutable {return ++a;}; //默认情况下,对于一个值被拷贝的变量,lambda不会改变其值,如果我们希望能改变一个被捕获的变量的值,就必须加上关键字mutable。
a=10;;
func_lambda_3();
} //所以可变lambda可以省略参数列表
//