• c++Lambda


    Lambda 表达式不仅具有函数指针的灵活性,还可以通过捕获局部变量提高可扩展性。本文介绍 Lambda 表达式的语法和用法。

    简介

    Lambda 可能是最新的 C++11 标准的典型特性之一。Lambda 表达式把函数看作对象。Lambda 表达式可以像对象一样使用,比如可以将它们赋给变量和作为参数传递,还可以像函数一样对其求值。

    当一个函数需要将另一个函数用作参数时,可以使用 Lambda。例如,C qsort() 函数接受一个指向比较函数的指针,如清单 1 所示。

    #include <stdlib.h> 
     #include <stdio.h> 
     static int intcompare(const void *p1, const void *p2) 
     {   
     int i = *((int *)p1);  
     int j = *((int *)p2); 
     return (i < j) ;
     }  
     int main() 
     {   
     int a[10] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; 
     qsort((void *)a, 10, sizeof (int), intcompare);
     for (int i = 0; i < 10; i++) { printf("%d ", a[i]); }  
     printf("
    "); 
     return 0;  }

    清单 1

    清单 1 中的代码有以下几点不足:

    • 比较函数需要单独声明。这增加了将错误的比较函数传递给 qsort() 操作的风险。
    • 比较函数接受 void * 参数,因此缺失了某种程度的类型检查。
    • 比较函数看不到任何局部作用的变量。因此,如果存在其他影响排序的因素,必须在更大范围内声明。

    清单 2 显示重新编写后的清单 1 中的示例,将 C++ std::sort() 算法与 lambda 表达式结合使用。由于 std::sort() 是一个模板,因此会保留所有类型信息。注意如何在通常出现函数名的位置编写 lambda 表达式。

    #include <algorithm> 
     int main() 
     {
     int a[10] = { 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };   
    std::sort( a, &a[10], [](int x, int y){ return x < y; } );
        for(int i=0; i<10; i++) { printf("%i ", a[i]); }  
      printf("
    ");    
      return 0; 
      }

    清单 2

    Lambda 表达式的基本语法

    Lambda 表达式本质上与函数声明非常类似。我们可以提取清单 2 中的 lambda 表达式,详加说明。提取的 lambda 表达式如清单 3 所示:

    [](int x, int y){ return x < y ; }

    清单 3

    如果我们将 lambda 表达式比作函数,可以看到它与函数名对应的是一对空的方括号,即捕获表达式。这些括号表示后面跟着一个 lambda 表达式。这些方括号不必为空;稍后将讨论其内容。

    如果 lambda 主体只含一个返回类型,则暗示返回的表达式类型为 lambda 返回类型。如果要显式指定返回类型,需使用新的 C++11 语法表示函数声明中的后置返回类型。对于返回类型 T 的普通函数,您可以这样编写:

    auto foo(...) -> T { ... }

    对于 lambda,您需要要这样编写:

    [] (...) -> T { ... }

    lambda 表达式的其余部分与常规 C 或 C++ 函数主体类似。

    将 Lambda 传递到函数指针

    C++11 标准库中有一个名为 function 的模板,它可以接受指定类型的函数或者具有匹配的返回类型和参数列表的 lambda。这将产生一个指向函数类型的指针,例如,清单 4 可用作函数参数类型,接受 int 参数,返回 void。您可以向其传递任何类似匹配函数或 lambda 的内容。

    std::function<void(int)>
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    bool cmp(int a, int b)
    {
        return  a < b;
    }
    
    int main()
    {
        vector<int> myvec{ 3, 2, 5, 7, 3, 2 };
        vector<int> lbvec(myvec);
    
        sort(myvec.begin(), myvec.end(), cmp); // 旧式做法
        cout << "predicate function:" << endl;
        for (int it : myvec)
            cout << it << ' ';
        cout << endl;
    
        sort(lbvec.begin(), lbvec.end(), [](int a, int b) -> bool { return a < b; });   // Lambda表达式
        cout << "lambda expression:" << endl;
        for (int it : lbvec)
            cout << it << ' ';
    }
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int main()
    {
         int a = 900;
         auto f = [a] { cout << a << endl; };  
         cout <<  ++a << endl;
         return 0;
    }
    root@ubuntu:~/c++# g++ -std=c++11  lam.cpp -o lam
    root@ubuntu:~/c++# ./lam 
    901
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int main()
    {
         int a = 900;
         auto f = [a] { cout << ++a << endl; };
         f();
         cout <<  ++a << endl;
         return 0;
    }
    root@ubuntu:~/c++# g++ -std=c++11  lam.cpp -o lam
    lam.cpp: In lambda function:
    lam.cpp:7:31: error: increment of read-only variable ‘a’
          auto f = [a] { cout << ++a << endl; }; 
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int main()
    {
         int a = 900;
         auto f = [&a] { cout << ++a << endl; };
         f();
         cout <<  ++a << endl;
         return 0;
    }
    root@ubuntu:~/c++# g++ -std=c++11  lam.cpp -o lam
    root@ubuntu:~/c++# ./lam 
    901
    902
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int main()
    {
         int a = 900;
         auto f = [](int a) mutable { cout << ++a  << endl; };
         f(300);
         cout <<  ++a << endl;
         return 0;
    }
    
    root@ubuntu:~/c++# g++ -std=c++11  lam.cpp -o lam
    root@ubuntu:~/c++# ./lam
    301
    901
    root@ubuntu:~/c++# 
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int main()
    {
         int a = 900;
         auto f = [](int b) { cout << ++a + b << endl; };
         f(300);
         cout <<  ++a << endl;
         return 0;
    }
    ~
    lam.cpp: In lambda function:
    lam.cpp:7:37: error: ‘a’ is not captured
          auto f = [](int b) { cout << ++a + b << endl; }; 
                                         ^
    lam.cpp:7:16: note: the lambda has no capture-default
          auto f = [](int b) { cout << ++a + b << endl; }; 
                    ^
    lam.cpp:6:10: note: ‘int a’ declared here
          int a = 900;
              ^

    #include <iostream>
    #include <algorithm>
    using namespace std;
    int main()
    {
    int a = 900;
    [](int a) mutable { cout << ++a << endl; }(20);
    cout << ++a << endl;
    return 0;
    }

    root@ubuntu:~/c++# g++ -std=c++11  lam.cpp -o lam
    root@ubuntu:~/c++# ./lam
    21
    901
    #include <iostream>
    #include <algorithm>
    #include<functional>
    using namespace std;
    int main()
    {
         int a = 900;
         function<int(int x)> f_display_42 = [](int x) { return ++x; };
         cout << f_display_42(44) << endl;
         cout <<  ++a << endl;
         return 0;
    }
    root@ubuntu:~/c++# g++ -std=c++11  lam.cpp -o lam
    root@ubuntu:~/c++# ./lam
    45
    901
    #include <iostream>
    #include <algorithm>
    #include<functional>
    using namespace std;
    int main()
    {
         int a = 900;
         function<int(int x)> f_display_42 = [a](int x) { return a+x; };
         cout << f_display_42(44) << endl;
         cout <<  ++a << endl;
         return 0;
    }
    root@ubuntu:~/c++# g++ -std=c++11  lam.cpp -o lam
    root@ubuntu:~/c++# ./lam
    944
    901
    捕获形式说明
    [] 不捕获任何外部变量
    [变量名, …] 默认以值得形式捕获指定的多个外部变量(用逗号分隔),如果引用捕获,需要显示声明(使用&说明符)
    [this] 以值的形式捕获this指针
    [=] 以值的形式捕获所有外部变量
    [&] 以引用形式捕获所有外部变量
    [=, &x] 变量x以引用形式捕获,其余变量以传值形式捕获
    [&, x] 变量x以值的形式捕获,其余变量以引用形式捕获

     https://www.cnblogs.com/DswCnblog/p/5629165.html

    https://www.oracle.com/cn/servers/technologies/howto-use-lambda-exp-cpp11.html

  • 相关阅读:
    web.xml报错
    mysql字符集问题汇总
    查询所有表中的某个数存储过程脚本
    SQL Server生成数据库的数据字典存储过程
    浏览器无法访问虚拟机的服务器
    搭建lnmp环境,nginx的配置文件/etc/nginx/nginx.conf
    在centos6.5下搭建lnmp
    Linux服务器关联Git,通过执行更新脚本实现代码同步
    CentOS yum 安装时错误 Errno 14 Couldn't resolve host 解决办法
    LinqToSQL3
  • 原文地址:https://www.cnblogs.com/dream397/p/14605242.html
Copyright © 2020-2023  润新知