C++11 lambda表达式

来源:互联网 发布:淘宝上哪家热干面好吃? 编辑:程序博客网 时间:2024/06/10 02:59

lambda表达式是C++11新特征中的一部分。lambda和仿函数有些许相同的地方,仿函数在之前的博文中已经具体的提及到了。

1、函数调用运算符(仿函数)

仿函数的实质就是在类中重载了()运算符,使得对象调用()的形式与函数的调用形式基本一致。仿函数在之前的博客中已经有详细的解释,具体可查阅之前的博客。

2、lambda表达式

一个lambda表达式表示一个可以调用的单元。我们可以将它理解成一个未命名的内联函数。和函数相似的是lambda具有一个返回类型、一个参数列表和一个函数体。
lambda表达式的形式可以抽象表示为:
[capture list] (parameter list) -> return type {function body}
capture list:捕获列表,lambda表达式中局部变量定义的列表。捕获列表不能省略,但是里面可以不定义内容直接写成[]形式。

              
parameter list:参数列表,这个和普通函数没有什么区别,值得注意的是,lambda表达的参数列表中不支持默认参数!                        参数列表在lambda表达式中是可以省略的部分。
return type:    返回值类型,和普通函数一样。返回值类型在lambda表达式中是可以省略的部分。
function body:  函数体,和普通函数一样。不可省略。
lambda表达式必须使用尾置返回来指定返回类型。


(1)忽略参数列表和返回类型的lambda表达式

auto f = [] {return 42};


上述,定义了一个可调对象f,他不接受参数,返回42。
lambda表达式的调用方式也与普通函数的调用方式相同,都是使用调用运算符。


cout<< f() << endl;


完整例子如下:


#include <iostream>using namespace std;int main(){auto f = []{ return 42; };cout << f() << endl;return 0;}

(2)向lambda 传递参数


首先看一个例子。现在要求我们将一个vector容器中的string数据按照string的长短进行排序。根据STL中algorithm,有sort函数可以使用。sort函数在cpp标准中的定义如下:
a> template <class RandomAccessIterator>
   void sort (RandomAccessIterator first, RandomAccessIterator last);
b> template <class RandomAccessIterator, class Compare>
   void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

其中b版本可以带入一个我们自己定义的排序规则函数。按照分析可以写出如下的代码:

bool isShorter(const string &s1, const string &s2){return s1.size() < s2.size();}//按照排序规则对words序列中的元素进行排序sort(words.begin(), words.end(), isShorter)使用lambda完成一个和isShorter函数一样功能的表达式:auto f = [](const string& s1, const string& s2){return s1.size() < s2.size();};

(3)使用捕获列表


一个lambda表达式通过将局部变量包含在其捕获列表中来指出将会使用这些变量。捕获列表指引lambda在其内部访问局部变量所需的信息。

void biggies(vector<string> &words, vector<string>::size_type sz){elimDups(words);//将words按照字典序排序,删除重复单词//按照长度排序,长度相同的单词维持字典顺序stable_sort(words.begin(),words.end(),            [](const string& s1, const string& s2){return s1.size() < s2.size();});auto wc = find_if(words.begin(),words.end(),  [sz](const string &a)       {return a.size() >= sz;};}

3、lambda捕获和返回


当定义一个lambda的时候,编译器生成一个与lambda对应的新的(未命名的)类类型。当传递一个lambda时,同时定义了一个新类型和该类型的对象:传递的参数就是此编译器生成的类类型的未命名的对象。类似的,当使用auto定义一个用lambda初始化的变量时,定义一个从lambda生成的类型的对象。






0 0
原创粉丝点击