C++作者Bjarne Stroustrup在他的书***The C++ Programming Language***第11章(ISBN-13: 978-0321563842)中给出了对lambda expression的最佳解释之一:
What is a lambda expression?
lambda 表达式,有时也称为 lambda
功能或(严格来说不正确,但通俗地说)作为
lambda,是定义和使用匿名函数对象的简化符号。不是用 operator() 定义命名类,而是稍后创建该类的对象,最后
调用它,我们可以使用简写。
When would I use one?
当我们想要将操作作为
算法的论据。在图形用户界面的上下文中
(以及其他地方),此类操作通常称为回调。
What class of problem do they solve that wasn't possible prior to their introduction?
在这里,我想使用 lambda 表达式完成的每个操作都可以在没有它们的情况下解决,但需要更多的代码和更大的复杂性。 Lambda 表达式这是优化代码的方式,也是使其更具吸引力的方式。像 Stroustup 一样悲伤:
有效的优化方法
Some examples
通过 lambda 表达式
void print_modulo(const vector<int>& v, ostream& os, int m) // output v[i] to os if v[i]%m==0
{
for_each(begin(v),end(v),
[&os,m](int x) {
if (x%m==0) os << x << '\n';
});
}
或通过函数
class Modulo_print {
ostream& os; // members to hold the capture list int m;
public:
Modulo_print(ostream& s, int mm) :os(s), m(mm) {}
void operator()(int x) const
{
if (x%m==0) os << x << '\n';
}
};
甚至
void print_modulo(const vector<int>& v, ostream& os, int m)
// output v[i] to os if v[i]%m==0
{
class Modulo_print {
ostream& os; // members to hold the capture list
int m;
public:
Modulo_print (ostream& s, int mm) :os(s), m(mm) {}
void operator()(int x) const
{
if (x%m==0) os << x << '\n';
}
};
for_each(begin(v),end(v),Modulo_print{os,m});
}
如果您需要,您可以命名lambda expression,如下所示:
void print_modulo(const vector<int>& v, ostream& os, int m)
// output v[i] to os if v[i]%m==0
{
auto Modulo_print = [&os,m] (int x) { if (x%m==0) os << x << '\n'; };
for_each(begin(v),end(v),Modulo_print);
}
或者假设另一个简单的样本
void TestFunctions::simpleLambda() {
bool sensitive = true;
std::vector<int> v = std::vector<int>({1,33,3,4,5,6,7});
sort(v.begin(),v.end(),
[sensitive](int x, int y) {
printf("\n%i\n", x < y);
return sensitive ? x < y : abs(x) < abs(y);
});
printf("sorted");
for_each(v.begin(), v.end(),
[](int x) {
printf("x - %i;", x);
}
);
}
将生成下一个
0
1
0
1
0
1
0
1
0
1
0 排序x - 1;x - 3;x - 4;x - 5;x - 6;x - 7;x - 33;
[] - 这是捕获列表或lambda introducer:如果lambdas 不需要访问其本地环境,我们可以使用它。
引用书:
lambda 表达式的第一个字符始终是 [。一个拉姆达
介绍人可以采取多种形式:
• []:一个空的捕获列表。这
意味着不能使用来自周围上下文的本地名称
在 lambda 体内。对于这样的 lambda 表达式,数据是从
参数或来自非局部变量。
• [&]:隐式捕获
参考。可以使用所有本地名称。所有局部变量都是
通过引用访问。
• [=]:按值隐式捕获。所有本地
可以使用名称。所有名称均指局部变量的副本
在调用 lambda 表达式时获取。
• [capture-list]: 显式捕获;捕获列表是要通过引用或值捕获(即存储在对象中)的局部变量的名称列表。名称以 & 开头的变量被捕获
参考。其他变量按值捕获。捕获列表可以
还包含 this 和名称后跟 ... 作为元素。
• [&, capture-list]:通过引用隐式捕获列表中未提及名称的所有局部变量。捕获列表可以包含它。列出的名称前面不能有 &。中命名的变量
捕获列表按值捕获。
• [=, capture-list]:按值隐式捕获列表中未提及名称的所有局部变量。捕获列表不能包含此内容。列出的名称必须以 & 开头。捕获列表中命名的变量是通过引用捕获的。
请注意,以 & 开头的本地名称总是被
引用和前面不带 & 的本地名称总是被
价值。只有通过引用捕获才允许修改变量
调用环境。
Additional
Lambda expression 格式
其他参考资料: