相当于一个可以在函数内部定义的函数,主要用于可以把谓词当做参数的算法。
格式如下:
[捕获列表] (参数) {函数体}
捕获列表中的是函数可能要用到的这个lambda所在函数中的局部变量,其它的跟普通函数差不多。捕获列表的作用主要是一般算法的谓词只接受一个参数或者两个参数,如果要用到不止这么多,就要用到捕获列表。另外如果在当前这个函数的外部的变量,就可以不用捕获列表,函数体内直接使用了。
#include<iostream>
#include<vector>
#include<array>
#include<algorithm>
using namespace std;
int main()
{
vector<string>v={"a","b","c","ab","bc","abc","bcd","cde","abcde","bcd"};
int n=3;
sort(v.begin(),v.end(),
[](string a,string b)
{
return a>b;
}//比较常用的自定义排序算法的谓词
);
for(auto &i:v)
{
cout<<i<<' ';
}
puts("");
auto p=find_if(v.begin(),v.end(),
[n](string a)
{
return (int)a.size()>=n;
}//这里是返回第一个长度大于n的字符串,由于要用到n,所以用捕获列表保存,m是main函数外的,所以可以直接用
);
cout<<(*p)<<endl;
system("pause");
}
关于捕获列表
lambda
在创建时实际上会建立一个无名的类,同时这个类会建立一个基于捕获列表的对象,所以如果按照我们上面的例子,那么这个lambda不管什么时候调用,其捕获列表内的值都会是创建时候的值。如果我们想实时改变lambda捕获列表里里面的值,就可以类似使用普通函数一样,传一个引用进去,具体看代码。
#include<iostream>
#include<vector>
#include<array>
#include<algorithm>
using namespace std;
int main()
{
int a=1;
auto f=[&a](){
return a;
};
auto g=[a](){
return a;
};
cout<<f()<<' '<<g()<<endl; //答案为1 1
a--;
cout<<f()<<' '<<g()<<endl; //答案为0 1 g()中的a是值传递,所以保存的还是创建时的拷贝。
system("pause");
}
以上的例子都是显式得表示捕获列表,如果所要用到的局部变量都是值或者引用的话,就可以用一个 =
或&
隐式表示,其中=
表示值传递,&
表示引用。
#include<iostream>
#include<vector>
#include<array>
#include<algorithm>
using namespace std;
int main()
{
int a=1;
auto f=[&](){
return a;
};
auto g=[=](){
return a;
};
cout<<f()<<' '<<g()<<endl;
a--;
cout<<f()<<' '<<g()<<endl; //输出同上一段代码
system("pause");
}
同时,如果我们希望一部分变量是引用,一部分是值,那么可以隐式显式混用。但是要注意的是,这里规定第一个必须是隐式的,后面显式的变量必须跟隐式不同样是值或者不同样是引用。
#include<iostream>
#include<vector>
#include<array>
#include<algorithm>
using namespace std;
int main()
{
int a=1;
int b=2;
auto f=[&,b](){
return a;
};
auto g=[=,&b](){
return a;
};
cout<<f()<<' '<<g()<<endl;
a--;
cout<<f()<<' '<<g()<<endl;//没有用到b,只是想介绍写混用的规则
system("pause");
}
可变lambda
在拷贝列表的变量为值传递时,由于它是个右值,所以是不能动的,如果想要对其做些变化的操作的话,就要在函数体前加上mutable
的修饰。
#include<iostream>
#include<vector>
#include<array>
#include<algorithm>
using namespace std;
int main()
{
int a=1;
int b=2;
auto f=[a]() mutable {
a++;
return a;
};
cout<<f()<<endl; //输出2
a--; //即使加上了这个修饰,f()中的a仍然只是a的一个拷贝,所以这个a变化,那边的a不会有有影响。
cout<<f()<<endl; //输出3 f()中拷贝的a继续加一
system("pause");
}
关于lambda的返回类型
C++ primer中说如果函数体中不止一句简单return语句,那么返回值必须显式地写出来,否则返回值会自动变成void,也就是如下形式
#include<iostream>
#include<vector>
#include<array>
#include<algorithm>
using namespace std;
const int m=4;
struct node
{
int a,b,c;
node(int a,int b,int c):a(a),b(b),c(c){}
};
int main()
{
vector<node>v={node(1,2,3),node(2,3,4),node(1,3,4)};
sort(v.begin(),v.end(),
[](node a,node b) -> bool //显式返回值类型
{
if(a.a==b.a&&a.b==b.b) return a.c>b.c;
if(a.a==b.a) return a.b>b.b;
return a.a>b.a;
}
);
for(auto i:v)
{
cout<<i.a<<' '<<i.b<<' '<<i.c<<endl;
}
system("pause");
}
但是经过实操不显式好像不会让返回值变成void,懂的教下。
#include<iostream>
#include<vector>
#include<array>
#include<algorithm>
using namespace std;
const int m=4;
struct node
{
int a,b,c;
node(int a,int b,int c):a(a),b(b),c(c){}
};
int main()
{
vector<node>v={node(1,2,3),node(2,3,4),node(1,3,4)};
sort(v.begin(),v.end(),
[](node a,node b)
{
if(a.a==b.a&&a.b==b.b) return a.c>b.c;
if(a.a==b.a) return a.b>b.b;
return a.a>b.a;
}
);
for(auto i:v)
{
cout<<i.a<<' '<<i.b<<' '<<i.c<<endl;
}
system("pause");
}