• C++11 --- lambda表达式



    可调用对象有:
    函数指针、仿函数、lambda表达式、包装器

    本节介绍lambda表达式
    C++11语法中出现了Lambda表达式,lambda表达式可以理解为一个匿名函数

    格式

    [捕捉列表] (参数列表) mutable -> 返回值类型 {函数体}
    
    • 1

    捕捉列表:在lambda函数的开始位置,编译器根据[ ]来判断接下来的代码是否为lambda函数,能够捕捉上下文中的变量供lambda函数使用,不可省略。

    参数列表:与普通函数的参数列表一致,如果不需要参数传递,( )可省略

    mutable:默认不能修改值捕获的变量 (下文介绍) ,当lambda要修改值捕获的变量时,必须添加mutable声明使用该修饰符时,参数列表不可省略(即使参数为空)。

    返回值类型:没有返回值时此部分可省略,返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。

    函数体:在函数体内,可以使用参数、捕获到的变量。

    因此C++11中最简单的lambda函数为:

     []{}; //该lambda函数不能做任何事情
    
    • 1

    使用方式

    可以写在需要可调用对象的地方,比如sort第三个参数:

    int main()
    {
    	  Goods gds[] = { { "苹果", 2.1 }, { "荔枝", 3 }, { "橙子", 2.2 }, {"菠萝", 1.5} };
    	  sort(gds, gds + sizeof(gds) / sizeof(gds[0]), 
    	  [](const Goods& l, const Goods& r)->bool
    	  {
    	      return l._price < r._price;
    	  });
    	  
    	 return 0; 
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    单独不能直接使用,可借助auto将其赋值给一个变量来调用:

      auto f = []{ cout<<"hello"<<endl; };
      f();
    
    • 1
    • 2

    允许使用lambda表达式拷贝构造一个新的副本:

       auto f2 = []{ cout<<"hello"<<endl; };
       auto f3(f2);
    
    • 1
    • 2

    可以将lambda表达式赋值给相同类型的函数指针:

     void (*PF)();
     auto f2 = []{ cout<<"hello"<<endl; };
     PF = f2;
     PF();
    
    • 1
    • 2
    • 3
    • 4

    原理

    编译器对于lambda表达式是按照仿函数的方式处理的
    即:如果定义了一个lambda表达式,编译器会生成一个仿函数,仿函数名称是 lambda_uuid

    uuid🔗

    uuid唯一,所以lambda表达式之间不能互相赋值,即使两个lambda表达式“长得很像”

    捕捉列表

    捕捉列表描述了父作用域哪些数据可以被lambda使用,以及传值还是传引用。
    [var]:表示值传递方式捕捉变量var
    [=]:表示值传递方式捕获所有父作用域中的变量(成员函数这样使用会捕获到this指针)
    [&var]:表示引用传递捕捉变量var
    [&]:表示引用传递捕捉所有父作用域中的变量(成员函数这样使用会捕获到this指针)

    值捕获是发生在lambda创建时,而非调用时。

    捕捉列表使用注意事项:

    1. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。
      比如:[=, &a, &b]:以引用传递的方式捕捉变量a和b,值传递方式捕捉其他所有变量 [&,a,
      this]:值传递方式捕捉变量a和this,引用方式捕捉其他变量

    2. 捕捉列表不允许变量重复传递,否则就会导致编译错误。 比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复

    3. lambda无法捕获任何static变量、全局变量,不过可以在lambda表达式内部直接访问。

  • 相关阅读:
    Docker | 容器互联互通
    Mybatis当传入参数为0时,动态sql语句条件不生效
    unity3d客户端框架 基于类对象池的可回收变量 代码实现
    应用安全四十二:SSO安全
    【FPGA教程案例22】基于FIFO核的可控任意长度延迟器设计
    java猜四位数字游戏
    vue编写分页组件
    读时加写锁,写时加读锁,Eureka可真的会玩
    kotlin:LogKit
    【电商运营】社交媒体营销策略该如何制定?
  • 原文地址:https://blog.csdn.net/sqjddb/article/details/125988335