Lambda表达式

Lambda所做的一切都不具备创新性,相对于手工定义函数,它无非只是节约了大量的打字时间,但lambda的引入使得函数对象的创建更为便捷,在极大程度上影响了C++的日常开发。如果没有lambda,STL中的”_if”算法(例如std::find_if,std::remove_if,std::count_if等)只能与琐碎的谓词搭配使用,lambda使这些算法枯木逢春(某些需要自定义比较函数的算法亦是如此,例如std::sort,std::nth_element,std::lower_bound)。在STL之外,lambda可以为std::unique_ptr和std::shared_ptr快速创建自定义删除器(见Item18、19),并且它们使线程API中条件变量的谓词规范变得简单明了。

在开始本章之前,我们对lambda进行一个简单的复习:

  1. lambda是一个表达式,当其应用于算法时,其形式大致如下所示:
    1
    2
    std::find_if(container.begin(), container.end(),
    [](int val) { return 0 < val && val < 10; });
  2. 闭包(closure)是一个由lambda创建的运行期对象。
    根据lambda捕获模式的不同,闭包保存捕获数据的副本或引用。在上文对std::find_if的调用中,闭包是运行期find_if所采纳的第三个参数。
  3. 闭包类(closure class)是一个能够实例化闭包的类。
    每个lambda都会导致编译器生成一个唯一的闭包类,lambda中的语句成为其闭包类的成员函数中的可执行指令。

一般而言,lambda用于创建仅用作函数参数的闭包,上文即是这种情况。但闭包具备拷贝性,所以可能会出现对于某些lambda闭包类型的多个闭包(这似乎很容易理解,因为lambda产生了闭包类)。例如在以下代码中:

1
2
3
4
5
6
7
8
{
int x; // x is local variable

auto c1 = [x](int y) { return x * y > 55; }; // c1 is copy of the closure produced by the lambda
auto c2 = c1; // c2 is copy of c1
auto c3 = c2; // c3 is copy of c2

}

c1,c2和c3都是由lambda所生成的闭包的副本。

在非正式情况下,lambda,闭包和闭包类完全可以等而视之。但在随后的章节中,区分编译期间存在的内容(lambda和闭包类),运行时存在的内容(闭包)以及它们如何相互关联非常重要。