C++中,一个lambda表达式表示一个可调用的代码单元。我们可以将其理解为一个未命名的内联函数。
1、lambda表达式的形式:
[capture list] (parameter list) -> return type { function body }
其中除了“[ ]”(其中捕获列表可以为空,但必须包含,不能省略)和“复合语句”(相当于具名函数定义的函数体),其它都是可选的。
注意:lambda表达式与函数:
它与普通函数不同的是,lambda必须使用尾置返回来指定返回类型(如果需要指定返回类型);不能有默认参数;lambda可以定义在函数内部。
那种只在一两个地方使用的简单操作,lambda表达式是最有用的。
如果需要在很多地方使用相同的操作,该操作又需要很多语句才能完成,通常使用函数更好。
如果lambda的捕获列表为空,通常可以用函数代替。但是,对于捕获局部变量的lambda,用函数替换就不容易了。
例如调用<algorithm>中的std::sort,ISO C++ 98 的写法是要先写一个compare函数:
bool compare (int &a,int &b)
{
return a > b;//降序排序
}
然后,再这样调用:
sort(a,a+n,compare);
然而,用C++ 11标准新增的Lambda表达式,可以这么写:
sort(a,a+n, [] (int a , int b) { returna > b ; });//降序排序
这样一来,代码明显简洁多了。
由于Lambda的类型是唯一的,不能通过类型名来显式声明对应的对象,但可以利用auto关键字和类型推导:
auto f = [] ( int a , int b) { return a > b ; };
2、捕获列表的使用
lambda可以出现在一个函数体中使用其局部变量,但它只能使用那些明确指明的变量(通过将这些局部变量包含在捕获列表中来使用)。
一个lambda表达式只有在其捕获列表中补货一个它所在的函数中的局部变量,才能在函数体中使用该变量。
捕获列表只用于局部非static变量,lambda可以直接使用局部static变量和在它所在函数之外声明的名字。
如果可能的话,应该尽量避免指针捕获和引用捕获。尽量保持lambda的变量捕获简单化。
值捕获:
void fucn1()
{
size_t v1 = 42;//局部变量
//将v1拷贝到名为f的可调用对象
auto f = [v1] {return v1; };
v1 = 0;
auto j = f(); //j为42;f保存了我们创建它时v1的拷贝
}
引用捕获:
void fucn2()
{
size_t v1 = 42;//局部变量
//对象f2包含v1的引用
auto f2 = [&v1] {return v1; };
v1 = 0;
auto j = f2(); //j为0;f2保存了v1的引用,并非拷贝
}
3、如果我们希望改变捕获的变量的值,必须在参数列表首加上关键字“mutable”!
void fucn3()
{
size_t v1 = 42;//局部变量
//f可以改变它所捕获的变量的值
auto f = [v1] () mutable {return ++v1; };
v1 = 0;
auto j = f(); //j为43;f保存了我们创建它时v1的拷贝
}
void fucn4()
{
size_t v1 = 42;//局部变量
//v1是一个非const的局部变量的引用,可以通过f2中的引用来改变它
auto f2 = [&v1] {return ++v1; };
v1 = 0;
auto j = f2(); //j为1
}