Lambda表达式(简称lambda),并没有给语言带来什么新的表现力,但确实产生了深刻的影响。可以很方便的利用lambda创建函数对象,这一点对C++ 的日常软件开发影响巨大。如果没有lambda表达式,STL的“_if”族算法(e.g., std::find_if, std::remove_if, std::count_if, etc.)只能使用最平凡的谓词来调用,但有了lambda后,使用复杂谓词来调用这些算法的应用并成井喷式。类似的情况同样发生在能够自定义比较函数的算法族(e.g., std::sort, std::nth_element, std::lower_bound, etc.)。除此之外,lambda也可以为std::unique_ptr and std::shared_ptr (see Items 18 and 19)快速创建自定义析构器,并且它们使线程API中条件变量的谓词规范同样简单明了(see Item 39)。在标准库之外,lambdas促进了用于一次性调用的回调函数、接口适应函数和特定于上下文的函数的动态规范。Lambdas确实使c++ 成为一种更令人愉快的编程语言。
围绕着lambda的一些术语可能令人迷惑。这里做一些澄清:
- lambda表达式也是表达式。它是源码的一部分。如下高亮的部分
std::find_if(container.begin(), container.end(), [](int val) { return 0 < val && val < 10; });- 闭包是由lambda创建的运行时对象。根据捕获模式的不同,闭包持有捕获数据的副本或引用。在上面std::find_if的调用中,闭包就是作为第三个实参在运行时传给std::find_if的对象。
- 闭包类就是实例化的闭包类。每个lambda表达式会触发编译器生成一个唯一的闭包类。lambda表达式中的语句会变成其闭包类成员函数中的可执行指令。
lambda表达式常用于创建闭包,且闭包仅被用作给函数传参。上面调用std::find_if就是这种情况。闭包也可以被拷贝,所以,对于某个lambda表达式的闭包类型,可以有多个闭包。如下代码:
{
int x; // x is local variable
…
auto c1 = // c1 is copy of the
[x](int y) { return x * y > 55; }; // closure produced
// by the lambda
auto c2 = c1; // c2 is copy of c1
auto c3 = c2; // c3 is copy of c2
…
}
c1, c2, and c3都是同一个lambda表达式产生的闭包副本。
在非正式场合,lambda表达式、闭包和闭包类的界线可以模糊一些。但在接下来的Items中,区分在编译期间存在的(lambdas和闭包类)、在运行时存在的(闭包)以及它们之间的关系通常是很重要的。