梁越

c++11新特性-lambda函数

0 人看过

使用详解

一个lambda表达式有一下形式

[ 捕获列表 ] ( 参数列表 ) -> 返回类型 { 函数体 }

参数列表和返回类型是可以忽略的

直接上几个例子吧

//不带参数直接返回
auto f = [] {return 42;};
cout<< f(); //打印42

//比较长短的函数
auto f = [] ( const string &a, const string &b ) { return a.size() > b.size(); }

//按长度排序
stable_sort(words.begin(), words.end(), f)

//查找符合某个条件的元素,这里是size() > sz的元素
auto wc=find_if( words.begin(), words,end() , [sz] ( const string &a ) { a.size() > sz })

值捕获

lambda捕获有两种捕获方式,分别是值捕获和引用捕获。
值捕获就像前面例子那样,与传值参数类似,采用值捕获的前提是变量可以拷贝复制,与参数不同,被捕获的变量的值是在lambda创建时拷贝,而不是调用时拷贝,比如:

int a = 30;
auto f = [a] {return a;};
a = 0;
auto b = f();  //b = 30
1
2
3

由于被捕获的变量的值是在lambda创建时复制的,所以随后对其的修改并不会影响到lambda内对应的值。
lambda也可以采用引用捕获变量,其工作方式和引用相同。例如:

int a = 30;
auto f = [&a] {return a;};
a = 0;
auto b = f();  //b = 0
1
2
3

引用捕获和返回引用有相同的问题和限制,如果我们采用引用方式捕获一个变量,就必须确保被引用对象在lambda执行时时存在的。所以一般建议保持lambda变量捕获简单化,对于普通变量,如int,float和string等类型,通常采用值捕获。对于捕获指正,迭代器或采用引用捕获,就必须要保证其在lambda执行时,迭代器、指正和引用的对象依然存在,且有预期值。

以上捕获为显示捕获,除了显示列出我们希望使用的变量外,还可以使用隐式捕获,即让编译器自己来推断我们需要捕获什么变量。我们在捕获列表中使用=或&,=表示采用值捕获,&表示引用捕获。