一个lambda表达式具有一个返回类型,一个参数列表和一个函数体;和函数不同,lambda定义在函数内部
表达式形式:
[capture list](parameter list)->return type{ function body}
//捕获列表 参数列表 返回类型 函数体
可以忽略参数列表和返回类型,但是必须永远包含捕获列表和函数体
(这种返回类型及叫做尾置返回:真正的返回类型在形参列表后面)
eg:
auto f = [ ]{return 5; }; //此处省略参数列表等价于指定一个空参数列表。省略返回类型auto可以自动推断
cout << f() << endl; //调用方式与普通函数的调用方式一样
vector
a = { 1, 2, 3, 4, 5, 6 };
auto f = [](vectorconst a){return *a.begin(); }; //传递的参数为:vector const a
cout << f(a) << endl;
空捕获列表表示不使用它所在函数的任何局部变量。
需要可以使用其局部变量,但是只能使用哪些明确指明的变量,一个lambda通过将局部变量包含在其捕获列表中来指出将会使用这些变量。
int aa = 10;
auto x = [aa](int b){return aa > b ? aa : b; };
eg:
#include
#include
#include
#include
using namespace std;
void elimDups(vector &world) //删除重复元素
{
sort(world.begin(), world.end()); //按字典序排序
auto do_unique = unique(world.begin(), world.end());
//使得每一个元素只出现一次,此时do_unique返回不重复区域的后一个位置
//unique并没有删除元素,而是覆盖了,他后面的元素仍然存在,但是我们不知道它的值是什么
for (auto &m : world){
cout << m <<" ";
}
cout << endl;
world.erase(do_unique, world.end());
//从开始重复的第一个元素,删除到最后
for (auto &m : world){
cout << m << " ";
}
cout << endl;
}
int main()
{
vector worlds = { "the", "quick", "red", "fox", "jumps", "over", "the", "slow", "red", "turtle" };
elimDups(worlds); //删除重复元素
stable_sort(worlds.begin(), worlds.end(),
[](const string &a, const string &b){return a.size() < b.size(); }); //按长度排序
for (auto &m : worlds){
cout << m << " ";
}
cout << endl;
int sz = 4;
auto world = find_if(worlds.begin(), worlds.end(), //获取一个迭代器,指向第一个满足size()>sz的
[sz](const string &a){return a.size() >= sz; });
auto num = worlds.end() - world; //满足size()>sz的长度
for_each(world, worlds.end(), [](const string &s){cout << s << " "; }); //打印满足的部分
system("pause");
return 0;
}
与传值参数类似,采用值捕获的前提是变量可以拷贝。与参数不同,被捕获的变量在创建时拷贝。
因此随后对其的修改不会影响到lambda内对应的值
int a = 10;
auto f = [a]{return a; };
引用捕获必须保证lambda在执行时被引用的对象是存在的。
int a = 10;
auto f = [&a]{return a; };
除了显示列出我们希望使用的来自所在函数的变量之外,还可以让lambda体中的代码来推断我们要使用哪些变量。为了指示编译器推断捕获列表,应在捕获列表中写一个&或=。&告诉编译器采用引用捕获方式,=则采用值捕获方式。
注意:
当混合使用隐式捕获和显示捕获时,捕获列表中第一个元素必须是一个“&”或“=”,此符号指定了默认捕获方式为引用或值。
当混合使用隐式捕获和显示捕获时,显示捕获必须使用与隐式捕获不同的方式。
#include
using namespace std;
int main()
{
int a = 10;
int b = 20;
auto f = [&, b]{return a > b ? a : b; };
auto ff = [=, &b]{return a < b ? a : b; };
cout << f() << endl;
cout << ff() << endl;
system("pause");
return 0;
}
默认情况下对于值被拷贝的变量,lambda不会改变其值。如果我们希望改变被捕获的值,则在参数裂变首加上mutable。
int a = 10;
//auto f = [a](){return ++a; }; 错误,a不能被修改
auto f = [a]()mutable{return ++a; };
一个引用捕获的变量是否能修改,依赖于指向的是一个const类型还是非const类型
即使用尾置返回类型:
transform(a.begin(), a.end(), a.begin(),
[](int i)->int{if (i < 0) return -i; else return i; });
网上搜的一段话:
lambda本质是模板,参数声明为auto借助了模板的推断机制。
auto func = [] (auto x, auto y) {
return x + y;
};
// 上述的lambda相当于如下类的对象
class X {
public:
template
auto operator() (T1 x, T2 y) const { // auto借助了T1和T2的推断
return x + y;
}
};