介绍lambda
一个lambda表达式表示一个可调用的代码单元,具有如下形式:
[capture list](parameter list) -> return type {function body}
其中,capture list是一个lambda所在函数中定义的局部变量的列表(一般为空),其他定义与普通函数相同。
我们可以忽略参数列表和返回类型,但必须永远包括捕获列表和函数体。lambda函数的调用方式与普通函数相同。
当定义一个lambda时,编译器生成一个与lambda对应的新的(未命名的)类类型。可以这样理解:当向一个函数传递一个lambda时,同时定义了一个新类型和该类型的一个对象。
向lambda传递参数
与普通函数不同,lambda不能有默认参数,因此,一个lambda调用的实参数目永远与形参数目相等。
捕获列表
一个lambda可以出现在一个函数中,使用其局部变量,但它只能使用那些明确指明的变量(包含在捕获列表中)。
例如:find_if函数
auto wc=find_if(words.begin(),words.end(),
[sz](const string &a){return a.size()>=sz;});
捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和它所在函数之外声明的名字
变量捕获方式
显式捕获
值捕获:前提是变量可以拷贝。被捕获的变量的值在lambda创建时拷贝,而不是调用时拷贝,因此随后对其修改不会影响lambda内对应的值。
voidfcnl(){
size_tv1=42;
autof=[v1]{returnv1;}
v1=0;
autoj=f();//j为42
}
引用捕获:
voidfcnl(){
size_tv1=42;
autof=[&v1]{returnv1;}
v1=0;
autoj=f();//j=0
}
当以引用方式捕获一个变量时,必须保证在lambda执行期间变量存在
隐式捕获
让编译器根据lambda体中代码来推断要使用哪些变量。为了指示编译器推断捕获列表,应在捕获列表中写一个&或=,&告诉编译器采用捕获引用方式,=则采用值捕获。
如果我们希望对一部分变量采用值捕获,一部分采用引用捕获,则可以混合使用显式捕获和隐式捕获,但显式捕获的变量必须使用与隐式捕获不同的方式(如果隐式是引用,显示必须是值)
void biggies(vector<string>&words,vector<string>::size_typesz,
osstream&os=cout,charc='')
{
//os隐式捕获,引用捕获,c显式捕获,值捕获
for_each(words.begin(),words.end(),[&,c](conststring&s){os<<s<<c});
//os显式,c隐式
for_each(words.begin(),words.end(),[=,&os](conststring&s){os<<s<<c});
}
可变lambda
如果希望能改变被捕获变量的值,必须在参数列表首加关键字mutable