Lambda表达式

本文最后更新于:August 25, 2022 pm

本系列博客中,我们会讨论lambda表达式的基本使用,以及需要注意的事项

lambda表达式没有为C++注入新的表达力,但它也毫无疑问是C++里最具颠覆性的内容。在任何需要lambda表达式的地方,只要我们愿意多敲几行,都可以避免使用lambda表达式。使用lambd表达式来创建函数对象是如此方便。没有lambda表达式时,标准库里那些”…_if”函数(比如std::remove_ifstd::find_if)是怎么用的——使用最简单的谓词。有了lambda表达式之后,就可以毫不费力地自行构建复杂谓词。对于std::sort, std::nth_element这类函数同样如此;有了lambda表达式,我们可以方便地为std::unique_ptrstd::shared_ptr自定义析构器,当为多线程API中的条件变量进行谓词声明时,它们同样也同样直截了当。在标准库外,lambda表达式经常被用于临时制造回调函数、接口适配函数,以及根据语境决定的一次性调用函数。lambda表达式让C++编程变得更加愉快了

这里着重区分一下相关概念:

  • lambda表达式 就是一个表达式,它是源代码的一部分,它在运行时并不存在

    下例中,lambda表达式只是第二行的部分

    1
    2
    3
    std::find_if(container.begin(), container.end(),
    [](int val){return val>0 && val <10 ;}
    );
  • 闭包(closure)是由lambda表达式创建的运行时对象。根据捕获模式的不同,闭包要么持有捕获数据的拷贝,要么持有其引用

    在上面的例子中,闭包是由第二行的lambda表达式创建的运行时对象,并且作为第三个实参被传递给std::find_if

  • 闭包类(closure class)是闭包实例化时对应的类。每一个lambda表达式都会使得编译器创建一个独一无二的闭包类,lambda表达式内的函数体在运行时称为闭包类的成员函数

w闭包可以被拷贝,理论上来说,可以创建多个闭包(运行时的对象),使得它们对应同一个闭包类,同时也对应同一个lambda表达式

1
2
3
4
5
6
7
8
9
10
11
12
{
int x;
......
auto c1= [x] (int y){ return x * y > 55;};
// c1 是从lambda表达式生成的闭包的拷贝,注意,赋值运算符右侧在运行时是一个对象

auto c2=c1; // c2 是c1的拷贝

auto c3=c2;// c3 是c2的拷贝

......
}

例中,c1c2c3都是lambda表达式创建的闭包的拷贝

导航

基本使用:lambda表达式基础使用

Item31:避免默认捕获模式

Item32:使用初始化捕获将对象移入闭包

Item33:使用decltype来转发auto&&类型的参数

Item34:尽量使用lambda,而非std::bind


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!