引入
C++11支持lambda表达式,lambda是一个匿名函数对象,它允许在函数体中直接定义。
一、初识lambda
lambda的结构是:[ ] () -> 返回值类型 { }。从左到右依次是:捕捉列表 函数参数 -> 返回值类型 函数体。
以下是一段用lambda实现的求和功能的函数:
#include<iostream>using namespace std;int main()
{//lambdaauto sum = [](int x, int y) -> int { return x + y; };cout << sum(1, 2) << endl;return 0;
}
这段代码的运行结果为:
二、lambda的注意事项
1.在使用lambda的时候,有几个参数是可以直接省略的:
1.参数列表可以省略(写() 或者不写())。
2.返回值可以省略(不写 -> 类型)。
除此之外的东西都不可省略(捕捉列表,函数体实现)。
#include<iostream>using namespace std;int main()
{//lambdaauto sum = []{ return 3 + 1; };cout << sum() << endl;return 0;
}
运行结果:
值得注意的是,在省略参数列表的时候(即不写 () ),返回值也要省略(不写-> 类型)。
2.捕捉列表
在C++中的lambda里,捕捉列表不可省略不写,它的作用是用来捕捉函数外部的变量,因为在lambda外部的变量是不被允许使用的,比如:
#include<iostream>using namespace std;int main()
{int a = 0, b = 1, c = 2;//lambdaauto sum = [a ,b , c] { cout << a << endl; return b + c; };cout << sum() << a << endl;return 0;
}
其中, cout << a << endl; 这个行为是不被允许的,编译器会报错:
那么当我们将也a写在捕捉列表中,它就没问题了。
当然了,如果需要捕捉的参数很多,那么lambda也提供了十分便捷的捕捉方式,那就是在捕捉列表里面直接写上 “=” 符号,这就是隐式捕捉lambda外的变量。然而,也可以在捕捉列表中写入“&”符号,表示隐式的引用捕捉。
a.写“=”的隐式捕捉:
#include<iostream>using namespace std;int main()
{int a = 0, b = 1, c = 2;//lambdaauto sum = [=] { cout << a << endl; return b + c; };cout << sum() << " " << a << endl;return 0;
}
运行结果如下:
b.写“&”的隐式捕捉:
#include<iostream>using namespace std;int main()
{int a = 0, b = 1, c = 2;//lambdaauto sum = [&] { cout << a << endl; return b + c; };cout << sum() << " " << a << endl;return 0;
}
运行结果如下:
这两种捕捉方式是有区别的:捕捉列表捕捉的参数默认是带有const属性的,除了引用捕捉以外,都不可在lambda里面修改捕捉到的参数。
a.写“&”,并且改变捕捉到的参数的捕捉:
#include<iostream>using namespace std;int main()
{int a = 0, b = 1, c = 2;//lambdaauto sum = [&] { cout << a << endl; a = 1; return b + c; };cout << sum() << " " << a << endl;return 0;
}
运行结果:
b.写“=”,并且改变捕捉到的参数的捕捉:
#include<iostream>using namespace std;int main()
{int a = 0, b = 1, c = 2;//lambdaauto sum = [=] { cout << a << endl; a = 1; return b + c; };cout << sum() << " " << a << endl;return 0;
}
运行结果(报错):
c.直接显式捕捉,并且改变捕捉到的参数的捕捉:
#include<iostream>using namespace std;int main()
{int a = 0, b = 1, c = 2;//lambdaauto sum = [a, b, c] { cout << a << endl; a = 1; return b + c; };cout << sum() << " " << a << endl;return 0;
}
运行结果(报错):
在使用隐式捕捉的时候,不必担心捕捉列表把所有的参数都捕捉到,这个类似于模板的按需实例化:当lambda里面用到了啥,它就捕捉啥:
#include<iostream>using namespace std;int main()
{int a = 0, b = 1, c = 2;//lambdaauto sum = [=] { return b + c; };cout << sum() << " " << a << endl;return 0;
}
这段代码使用了隐式捕捉,并且函数体没有使用a变量,让我们转到汇编:
可以看到只把c,b加载到寄存器中,并没有把a加载到寄存器,因此可以证明lambda的按需捕捉。