c++lambda表达式是c++11中的新增特性,最开始知道lambda表达式的时候,是学习python,python中的lambda表达式是用于简化函数编写,同样,我认为c++引入这个也是为了方便,lambda表达式并非不可替代,但是合理用lambda表达式,可能会事半功倍,至少也能少打一些字吧。
我在前面讲函数对象时说到过很多stl算法都需要一元谓词,二元谓词,先看一个例子:
template<typename T>
struct DisplayElement
{
void operator()(const T& element) const
{
cout<<element<<" ";
}
};
这是一个一个函数对象,(关于函数对象,请点击这儿),我们可以将其运用到std::for_each算法上:
for_each(VecIntegets.begin(),
VecIntegers.end(),DisplayElement<int>());
如果使用lambda表达式,可将上述代码简化为3行,不需要额外编写函数对象
for_each(VecIntegers.begin(),VecIntegers.end()
,[](int& element){cout<<element<<" ";});
编译器见到[](int element){cout<<element<<" ";
会自动展开为下面的形式
struct NoName
{
void operator() (const int& element) const
{
cout<<element<<"";
}
}
很方便对不对,下面正式介绍lambda表达式
定义:
1.一元函数对应的lambda表达式
[](Type parameterName){//lambda expression code here}
如果你愿意,也可以按引用传递参数:
[](Type & parameterName){....}
2.一元谓词对应的lambda表达式
一元谓词需要返回一个bool类型的参数,所以在你的括号里面需要返回一个bool的语句,例如用lambda编写一个判断奇偶的谓词
[](int &num){ return ((num%2)==0)}
显然二元谓词也就是有2个参数并返回bool类型的语句。
接受状态变量
上面编写了一个判断奇偶的一元谓词,若想让它更加通用,如接受指定的参数,判断能否被该参数整除,怎么办呢?
lambda表达式的通用语法
lambda表达式总是以方括号打头,并可以接受多个变量,谓词可在捕获列([…])中指定这些状态变量,并用分好隔开:
[StateVar1,StateVar2](Type& param){ //lambda code}
如果要在lambda表达式中修改这些状态变量,可以添加关键字mutable:
[StateVar1,StateVar2](Type& param) mutable { //lambda code}
如果想要更改后一直有效,应该采取引用传递:
[&StateVar1,&StateVar2](Type& param) mutable { //lambda code}
如果要向编译器明确指定返回类型,可使用->:
[&StateVar1,&StateVar2](Type& param)->returnType
mutable { //lambda code}
最后给一个用lambda编写二元谓词用于排序的例子:
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>
using namespace std;
template <typename T>
void DisplayContents (const T& Input)
{
for(auto iElement = Input.cbegin() // auto, cbegin and cend: c++11
; iElement != Input.cend ()
; ++ iElement )
cout << *iElement << endl;
}
int main ()
{
// Define a vector of string to hold names
vector <string> vecNames;
// Insert some sample names in to the vector
vecNames.push_back ("jim");
vecNames.push_back ("Jack");
vecNames.push_back ("Sam");
vecNames.push_back ("Anna");
cout << "The names in vector in order of insertion: " << endl;
DisplayContents(vecNames);
cout << "Names after sorting using default std::less<>: " << endl;
sort(vecNames.begin(), vecNames.end());
DisplayContents(vecNames);
cout << "Names after sorting using predicate that ignores case:" << endl;
sort(vecNames.begin(), vecNames.end(),
[](const string& str1, const string& str2) -> bool // lambda
{
string str1LowerCase;
// Assign space
str1LowerCase.resize (str1.size ());
// Convert every character to the lower case
transform (str1.begin (), str1.end (), str1LowerCase.begin (), tolower);
string str2LowerCase;
str2LowerCase.resize (str2.size ());
transform (str2.begin (), str2.end (), str2LowerCase.begin (),
tolower);
return (str1LowerCase < str2LowerCase);
} // end of lambda
); // end of sort
DisplayContents(vecNames);
return 0;
}