• C++ 新特性 | C++ 11 | lambda表达式


    一、lambda表达式

    1、简介

    是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。Lambda表达式可以表示闭包(注意和数学传统意义上的不同)。闭包就是能够读取其他函数内部变量的函数,可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。C++中的Lambda表达式从C++11开始引入,完整的声明如下:

    [capture] (params) -> returnType { body }
    
    • 1

    后面主要说明捕获形参返回类型函数体与具名函数的定义一致,没有区别。一个简单的Lambda表达式应用场景,如下:

    #include 
    #include 
    #include 
    using namespace std;
     
    int main()
    {
        vector<int> vec{ 3, 4 };
        //降序排序
        sort(vec.begin(), vec.end(), [](int a, int b) {return a > b; });
        for (size_t i = 0; i < vec.size(); i++)
        {
            cout << vec[i] << endl;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    2、创建一个有名称的lambda表达式

    lambda表达式创建的匿名函数,但是可以给这个匿名的函数起个名字,例如:

    #include 
    using namespace std;
     
    auto add = [](int x, int y)->int{
        return x + y;
    };
     
    int main(){
        int x = 10, y = 20;
        cout << add(x, y);
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    注意:不同于常规的函数,可以在函数的内部定义有名称的lambda表达式,add的实际类型随实现而异,它取决于编译器使用什么类型来跟踪lambda。

    3、返回类型

    如果没有指定返回类型,lambda表达式的返回类型从 return 语句推导,下面两行代码是等价的:

    //降序排序(不指定返回类型)
    sort(vec.begin(), vec.end(), [](int a, int b) {return a > b; });
    //降序排序(指定返回类型,没有返回值时可以指定为void类型)
    sort(vec.begin(), vec.end(), [](int a, int b) -> int {return a > b; });
    
    • 1
    • 2
    • 3
    • 4

    4、捕捉

    捕捉讲的是lambda表达式引用外部变量的方法,下面是常见的几种捕捉方式:

    • [ ]表示不捕捉任何变量
    • [=]表示按值传递的方法捕获父作用域的所有变量
    • [&]表示按引用传递的方法捕获父作用域的所有变量
    • [=, &a]表示按值传递的方法捕获父作用域的所有变量,但按引用传递的方法捕获变量a
    • [&, a]表示按引用传递的方法捕获父作用域的所有变量,但按值传递的方法捕获变量a

    5、lambda表达式的应用

    定义一个Number类,这个类的vector类型的成员num保存一些数字,这个类包含一个模板函数,这个函数返回在num里面可以被指定值N整除的元素的数目。例如,num = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10},N = 3;则函数返回的是在数组num里面可以被3整除的元素的数目。此时,如果在类里面针对每一个N都声明一个成员函数,这个类会变得非常庞大。因此,我们在这里声明一个函数模板,把一个函数作为参数传给这个模板函数,如下:

    #include 
    #include 
    using namespace std;
    
    class Number{
    private:
        vector<int> num;
    public:
        Number(int numSize = 10){
            for(int i = 1; i < numSize; i ++){
                num.push_back(i);
            }
        }
    
        template<typename Func>
        int findNumbers(Func func){
            int len = 0;
            for(vector<int>::iterator itr = num.begin(); itr != num.end(); itr ++){
                if(func(*itr)){
                    len ++;
                }
            }
            return len;
        }
    };
    
    // 定义一个函数
    bool isValid(int val){
        return val % 3 == 0;
    }
    
    // 定义一个函数符
    class FuncMode{
    private:
        int dv;
    public:
        FuncMode(int dv):dv(dv){}
        bool operator()(int x){
            return x % dv == 0;
        }
    };
    
    int main()
    {
        // 使用函数指针
        Number N(10);
        cout << N.findNumbers(isValid) << endl;
    
        // 使用函数符
        FuncMode func(3);
        cout << N.findNumbers(func) << endl;
    
        // 使用lambda表达式
        cout << N.findNumbers([](int x){return x % 3 == 0;}) << endl;
    
        return 0;
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    输出结果:

    3
    3
    3
    
    Process returned 0 (0x0)   execution time : 0.606 s
    Press any key to continue.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    代码随想录 Day-44|#70 爬楼梯(进阶)|#322 零钱兑换|#279 完全平方数
    Linux——开发工具yum与vim
    “BallCollisionCard“ app Tech Support(URL)
    四十六、Fluent壁面函数的选取依据
    Go:字符串Combinations组合算法(附完整源码)
    应用ceph块存储(ceph-13.2.10)
    什么是序列化和反序列化?
    小望电商通:无代码开发,轻松实现电商平台、客服系统和用户运营的集成
    一些可以访问gpt的方式
    华为防火墙基本原理工作方法总结
  • 原文地址:https://blog.csdn.net/cloud323/article/details/133049066