lambda表达式就是匿名函数,既然都称呼其为匿名函数了,也就是说它是一个函数!这个函数不用去设置函数名。
1,基本语法
[捕获列表](参数列表)mutable(可选)异常属性->返回类型{
//函数体
}
//举例:
//[]挂获列表(参数列表->返回值
[](int a.. int b) -> int{
//函数体
return a + b;
}
//该例子没有演示捕获列表以及mutable的用法,在后文会介绍。
1.1 匿名函数的用法(1)
可以看到,因为匿名函数没有名字,所以我们貌似必须在定义之后就开始实用该函数,这样的话匿名函数的其中一个用法如下:
int c=[](int a.. int b) -> int{
//函数体
return a + b;
}(1,2) //c接收返回值,(1,2)传入参数列表
1.2 匿名函数的用法(2)
上文用法的缺陷就在于一个lambda表达式只能调用一次,而实际上可以将整个函数体[](int a.. int b) -> int{ return a + b;}
看作一个类型,用auto
关键字去接。
auto f=[](int a.. int b) -> int{
//函数体
return a + b;
}
这样的话就可以在其他地方调用该匿名函数,例如int c=f(1,2);
2,捕获列表
匿名函数作为一个函数,在函数体中只对参数列表中传过来的变量以及全局变量可见。因此,如果想要得到其他局部变量的值,需要将该变量放入捕获列表中。
1,按值捕获
int i;
auto f=[i](int a.. int b) -> int{
//函数体
cout<<i;//只有将x捕获以后,函数体内部才可见。
return a + b;
如上面代码所示,匿名函数内部想要访问函数外部什么变量,只需在捕获列表中捕获即可。
注意:
1,不管该匿名函数何时调用,捕获的i始终是匿名函数声明时i的值,读者可以通过在不同位置更改i的值,然后在不同位置调用该匿名函数观察捕获的值。
2,从外面捕获的变量到匿名函数内部就会变成const类型,需要在函数声明中加入mutable关键字才能修改它的值。如下图所示:
3,即使使用mutable修改了从外部捕获的变量,外面的变量依然看不见该修改,在上面的例子中:执行完匿名函数,虽然函数内部捕获的i变成了11,但函数执行完外面的i还是10,读者可以自行验证;
**总结:**如果不使用mutable关键字,捕获列表相当于捕获了const类型的值;如果用了mutable关键字,则按值捕获的内容用法就和按值传递过来的形参一样,改变形参不会改变实参的值。
2,按引用捕获
了解了按值捕获以后,这里介绍一下按引用捕获,我们很容易就会猜想:按引用捕获的内容用法就和按引用传递过来的形参一样,改变形参的同时也会改变实参的值。事实上的确如此,读者可以尝试运行下面的代码验证一下。
同时也注意:不管该匿名函数何时调用,捕获的i始终是匿名函数声明时i的值,读者可以通过在不同位置更改i的值,然后在不同位置调用该匿名函数观察捕获的值。
3,补充
1)[a,b,c]
捕获多个外界变量用逗号隔开。
2)[=]
按值捕获外界所有变量,直接用等号代替。
3)[&]
按引用捕获外界所有变量,直接用与运算符代替。
4)[a,b&c,&d]
值和引用可以一起捕获。
5)匿名函数一般在工程中可以作为回调函数使用,例如: