Lambda函数
参考:CSDN
C++11开始,提供了对匿名函数的支持,成为Lambda函数(表达式)
通常,lambda函数用于封装传递给算法或异步方法的几行代码,对应不需要复用,且短小的函数,使用lambda函数可以增加代码的可读性
格式:
auto function=[capture list](parameters) mutable throw()->return-type {statement}
一般用一个auto变量来接收,然后通过这个变量名function(paramenters)调用,也可以直接附上参数,不需要auto变量名
[capture list](paramenters) mutable throw()->return-type {statement}(real paramenters)
例如:
auto function=[a,&b](int x) mutable ->int {return a+b+x;};
int m=function(20);
//another
int m=[a,&b](int x) mutable ->int {return a+b+x;}(20);
- 捕获列表:在C++规范中也称Lambda导入器,
[]
就是lambda引出符,编译器根据该引出符判断接下来的代码是否lambda函数,捕捉列表能捕捉上下文中的变量,供Lambda函数使用,也就相当于在函数中调用函数外的变量. - 参数列表:和普通函数的参数列表一致,如果不需要传递参数,则可以连同
()
一同省略 - 可变规格:
mutable
修饰符,默认情况下lambda函数总是一个const函数,mutable可以取消其常量性,如果使用了mutable,则参数列表不可省略 - 异常说明:用来抛出异常
- 返回类型:声明函数的返回类型,如果不需要返回值,则可以连同符号
->
一起省略,在返回类型明确的情况下,也可以省略该部分,让编译器对返回类型进行推到- 如
int a; return a+2;
编译器就能自动推导返回值类型为int
- 如
- lambda函数体:和普通函数别无二致,除了传入的参数,还可以使用捕获的变量
捕获列表
捕获列表就是lambda以值传递或引用传递的方式调用上下文的变量
- []表示不捕获任何变量
auto function=[]{std::cout<<"Hello";};
function();
这是一个简单的lambda例子,它的功能是输出"hello"
- [var]表示值传递的方式捕获变量var
int num=100;
auto function=[num]{std::cout<<num;};
function();
捕获就是在lambda表达式内部调用外面的变量,值传递相当于普通函数的值传递形式
- [=]表示值传递方式捕获父作用域的所有变量,包括this
int a=100;
float b=1.2;
auto function=[]{cout<<a<<endl<<b;};
function();
- [&var]表示引用传递捕捉变量var
int a=100;
auto function=[]{a++;cout<<a;};
function();
也就是能在lambda表达式中改变变量的值
- [&]表示引用传递捕捉父作用域的所有变量
int a=100;
float b=1.2;
auto fnction=[]{a++;
b+=2.3;
cout<<a<<endl<<b;};
function();
- [this]表示值传递方式捕捉当前的this指针
#include<iostream>
using namespace std;
class test{
public:
void sayHello(){
cout<<"hello"<<endl;
}
void lambda(){
auto function=[this]{this->sayHello();};
function();
}
};
int main(){
test t1;
t1.lambda();
}
-
[=,&]拷贝和引用混合
-
[=,&a,&b]:以值传递的方式捕捉其他所有变量,以引用方式捕捉a,b
-
[&,a,this]:以值传递捕捉a和this,其他用引用方式
-
-
捕捉列表不允许变量重复传递,如
-
[=,a]:已经捕捉了所有变量,重复捕捉a,会报错
-
[&,&this]:也是会报错
-
参数列表
格式和使用都和普通函数无二致
auto function=[](int x,int y){return x+y};
int a=function(100,200);
可变规格mutable
通过值传递方式捕获的变量在lambda中默认是const类型,只能输出,不能改变,使用mutable可以使其可变,但是只能在lambda中短暂使用,并不能影响到父作用域的变量
int a=1;
auto function=[a]() mutable {a++;};
function();
这时参数列表()
不能省略,可以使空的参数列表,但()
不能省
lambda的优缺点
优点:
-
可以直接在需要调用函数的位置定义短小精简的函数,不需要预先定义好函数
-
可以使代码结构更紧凑,因为调用的函数的定义就在旁边,不用向前后向后找,可读性更好
缺点:
-
增加了阅读代码的难度
-
无法复用
工作原理
编译器会把一个Lambda表达式生成一个匿名类的匿名对象,并在类中重载函数调用运算符,实现了一个operator()
方法
auto print=[]{cout<<"hello"<<endl;};
编译器会把它翻译为下面的代码:
class print_class{
public:
void operator()(void) const{
cout<<"hello"<<endl;
}
};
auto print=print_class();