• C++11之lambda表达式


      lambda表达式源于函数式编程的概念,它可以就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象。lambda表达式的类型在C++11中被称为“闭包类型”,也可以理解为是一个仿函数(带operator()类),其语法形式如下:

      [capture] (params) opt -> ret {body;};

      capture: 捕获列表;

      params: 参数列表;

      opt: 函数选项;

      ret: 返回值类型;

      body: 函数体。

      很多时候,lambda表达式的返回值是非常明显的,C++11中允许省略lambda表达式的返回值定义,即去掉“-> ret”部分,这样编译器就会自动推导出返回值类型。一个简单的lambda表达式如下:  

    #include "stdafx.h"
    #include<iostream>// std::cout
    
    int main()
    {
        auto f = [](int a, int b) -> int {return (a*b); };
        std::cout << f(3, 4) << std::endl; // output:12
    
        return 0;
    }

      lambda表达式中的捕获字段非常有用,捕获的意思是捕获外部变量在lambda函数体内部使用,有以下几种不同的捕获方式:

      []:不捕获外部的任何变量,如果在函数体内使用外部变量就会报错;

      [&]:以引用的方式捕获外部的所有变量,如果在函数体内改变外部变量值,外部变量值就会随之改变;

      [=]:以值的方式捕获外部的所有变量,如果在函数体内改变“外部变量值”,外部变量值不会改变;

      [=, &foo]:以值得方式捕获外部所有变量,并以引用的方式捕获foo变量;

      [bar]:以值得方式捕获bar变量,其他外部变量不捕获;

      [this]:捕获当前类中的this指针,让lambda表达式拥有和当前类成员函数同样的访问权限。如果已经使用了&或者=,则this是默认添加的。

      注意按值捕获和按引用捕获的区别,按值捕获将在lambda表达式中用到的外部变量进行了一份拷贝并且保存到了lambda闭包类型中,如果之后对所用到的外部变量进行修改,lambda表达式中用到的变量是不会改变的,因为该变量只是一份拷贝;按引用捕获则是直接对变量的值进行读取或操作,如代码所示:

    #include "stdafx.h"
    #include<iostream>// std::cout
    
    int main()
    {
        int numA = 0;
        int numB = 0;
        {
            auto f1 = [] {return numA; };// error,没有捕获外部变量
            auto f2 = [&numB] {return (--numB); };
            f2();
            std::cout << numB << std::endl;// -1
        }
    
        int numC = 100;
        int numD = 100;
        auto f3 = [=]() -> int {return (numC*numD); };
        numD = 99;
        std::cout << f3() << std::endl; // output:10000
    
        return 0;
    }
      有了lambda表达式,我们在使用for循环或者std::for_each的时候,就可以改写成如下形式:
    #include "stdafx.h"
    #include<iostream>// std::cout
    #include<list>
    #include <algorithm>
    int main()
    {
        std::list<int> l = { 1, 3, 5, 87, 64, 33, 0, -1, -100};
        int nCount = 0;
        std::for_each(l.begin(), l.end(), [&nCount](int val) {if (val > 50) nCount++; });
        std::cout << "The number larger than 50 in l is: " << nCount << std::endl;
    
        return 0;
    }

      总结一下,lambda表达式看起来和Java里边的匿名函数比较像,使用lambda表达式后,可以使程序变得非常简洁。但是,如果使用的lambda表达式包含的内容过多,或者lambda表达式的实体是好多地方都会用到的功能性函数,还是单独列出一个函数比较方便。

  • 相关阅读:
    CentOS 6.6 升级GCC G++ (当前最新版本为v6.1.0) (完整)
    telnet: Unable to connect to remote host: Connection refused
    bash: telnet: command not found (Linux安装telnet)
    telnet: Unable to connect to remote host: No route to host
    IP地址转换函数
    Linux 网络通信 API详解【转载】
    高效算法求解数独
    Java创建List、Map等集合对象的同时进行赋值操作
    根据先序遍历和中序遍历建立二叉树
    继承内部类时使用外部类对象.super()调用内部类的构造方法
  • 原文地址:https://www.cnblogs.com/jiayayao/p/6159892.html
Copyright © 2020-2023  润新知