首页 > 其他分享 >初识Lambda表达式(匿名函数)

初识Lambda表达式(匿名函数)

时间:2024-09-15 20:02:49浏览次数:11  
标签:int lambdaCap Order 匿名 初识 arg orders Lambda

0.问题导向

使用C++ STL实现订单按照创建时间从小到大排查。

using Order = struct tagOrder{
    unsigned int createTimspec;//创建时间戳
    int id;                    //订单号
    int totalPrice;           //总价
    int status;               //订单状态
    int payType;              //支付类型
};
void orderSortByTime(vector<Order>& orders)
{
    sort(orders.begin(),orders.end());
}

这样使用算法库的sort函数,编译报错:

error: no match for ‘operator<’ (operand types are ‘tagOrder’ and ‘tagOrder’)
 43 | return *__it1 < *__it2; }.

编译器只默认支持对基本数据类型的大小比较,例如int,long等。自定义数据结构需要自定义比较函数。

using Order = struct tagOrder{
    unsigned int createTimspec;//创建时间戳
    int id;                    //订单号
    int totalPrice;           //总价
    int status;               //订单状态
    int payType;              //支付类型
};
int compare(Order a,Order b)
{
    return a.createTimspec<b.createTimspec;
}
void orderSortByTime(vector<Order>& orders)
{
    sort(orders.begin(),orders.end(),compare);
}

你发现没有,这个自定义的函数compare很简单,只有一行代码。但是每次调用仍然有函数调用的开销,如果系统中有大量的调用需求,那么函数调用对性能的影响就不能忽视了。

using Order = struct tagOrder{
    unsigned int createTimspec;//创建时间戳
    int id;                    //订单号
    int totalPrice;           //总价
    int status;               //订单状态
    int payType;              //支付类型
};
void orderSortByTime(vector<Order>& orders)
{
    sort(orders.begin(),orders.end(),[](Order a,Order b){return a.createTimspec<b.createTimspec;});
}

按照上图方法也可以实现订单排序功能,sort函数的第三个参数替代了自定义的compare函数,"[](Order a,Order b){return a.createTimspec<b.createTimspec;}",这串就是我们今天要学习的Lambda表达式

1.Lambda表达式简介

Lambda表达式,也称为Lambada函数,实际是一个匿名函数(不需要定义函数名),主要的使用场景是函数入参,例如算法函数和异步函数。在C++中,从C++11开始引入Lambda表达式,之后在后面的C++14、C++17、C++20、C++23版本对Lambda表达式都有更新和扩展。这里我们选择最初的C++11版本,学习下Lambda表达式的基本语法和用法。

2.Lambda表达式语法

Lambda基本语法如下,包含捕获、参数、修饰符、返回类型和实体五部分。其中,修饰符和返回类型是可选部分。下面结合例子学习这五部分组成。
[capture](parameters) modifiers -> return-type {body}

3.Captures

1>捕获引用类型和值类型

int arg=10;
auto lambdaCap = [&arg] (){arg++;};//capture by reference
lambdaCap();
cout<<"arg="<<arg<<endl;//arg=11
return 0;

上图是捕获引用类型,不用解释。

int arg=10;
auto lambdaCap = [arg](){arg++;};//capture by value
lambdaCap();
cout<<"arg="<<arg<<endl;
//编译失败
main.cpp:265:30: error: increment of read-only variable ‘arg’

上图编译失败。

int arg=10;
auto lambdaCap = [arg]()mutable{arg++;};//capture by value
lambdaCap();
cout<<"arg="<<arg<<endl;//arg=10

增加mutable修饰符后编译通过,修饰符后面介绍。

2>捕获有效范围内的所有变量

 int arg=10;
 auto lambdaCap = [=]()mutable{arg++;};//capture by value
 lambdaCap();
 cout<<"arg="<<arg<<endl;//arg=10

上图是使用'='表示以值类型的方式捕获有效范围内的所有变量。

 int arg=10;
 auto lambdaCap = [&]()mutable{arg++;};//capture by value
 lambdaCap();
 cout<<"arg="<<arg<<endl;//arg=11

上图是使用'&'表示以引用的方式捕获有效范围内的所有变量。

4.Parameters

 auto lambdaAdd = [](int a,int b){return a+b;};
 cout<<"sum="<<lambdaAdd(1,2)<<endl;//sum=3

这里的参数和函数的入参类似,入参也可以有默认值。

 auto lambdaAdd = [](int a,int b=1){return a+b;};//capture by value
 cout<<"sum="<<lambdaAdd(1)<<endl;//sum=2

5.Body

实体部分类似普通函数的函数体,例如开端的订单排序例子中的Body返回创建时间的大小。

void orderSortByTime(vector<Order>& orders)
{
sort(orders.begin(),orders.end(),[](Order a,Order b){return a.createTimspec<b.createTimspec;});
}

6.Modifiers

可选部分,可以通过修饰符设置Lambda匿名函数的属性,例如在Captures部分我们用的mutable修饰符。还有noexcept、noreturn等。

int arg=10;
auto lambdaCap = [arg]()mutable{arg++;};//capture by value
lambdaCap();
cout<<"arg="<<arg<<endl;//arg=10

7.Return-Type

可选部分,如果不设置返回类型,则由编译器根据代码逻辑自动判断类型,例如上面的所有例子都是这样。如果设置返回类型,则强制要求编译器按照该类型返回。

auto lambdaAdd = [](int a,int b)->long{return (long)a+b;};
cout<<"sum="<<lambdaAdd(0x7FFFFFFF,0x1)<<endl;//sum=2147483648

8.总结

这里只是简单介绍了Lambda函数的产生以及基本的语法和使用场景,还有很多深奥的相关部分需要持续学习。日拱一卒无有尽,终不唐捐入海流。

标签:int,lambdaCap,Order,匿名,初识,arg,orders,Lambda
From: https://www.cnblogs.com/madadam/p/18405336

相关文章

  • 【Node.js】初识 RabbitMQ
    概述MQ顾名思义,是消息队列。RabbitMQ是一个消息队列系统,用于实现异步通信。基于AMQP。AMQP(高级消息队列协议)实现了对于消息的排序,点对点通讯,和发布订阅,保持可靠性、保证安全性。在Node.js的微服务架构中,RabbitMQ可以作为服务之间的消息传递中介,帮助解耦系统组件......
  • JavaSE初识(二)
    目录逻辑控制1.顺序结构2.分支结构2.1if结构2.1.1代码2.1.2应用 注意:2.2switch语句:3.循环结构3.1while循环3.2break3.3continue3.4for循环 3.5do...while循环4.输入输出 5.应用 5.1使用Scanner循环读取N个数字5.2猜数字游戏5.3......
  • Golang并发编程中匿名函数的应用与性能考量
    在Golang并发编程中,匿名函数是一种常见且非常实用的编程工具。匿名函数是指没有名称的函数,可以在函数内部定义和使用,或者作为参数传递给其他函数。这种方式不仅简化了代码结构,还能增强代码的灵活性,尤其在并发编程中,匿名函数的使用更能展现其优势。不过,如何合理使用匿名函数并在实......
  • C语言程序设计(初识C语言后部分)
    不必为小事所困,我们还有更大的世界。(4)模拟实现strlen(求字符串长度)#include<stdio.h>#include<assert.h>//模拟实现strlen(求字符串长度)intmy_strlen(constchar*str)//str指向的数据不需要被修改{ intcount=0; assert(str); while(*str!='\0') { count++;......
  • java匿名内部类
    定义内部类:将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。匿名内部类格式:new父类名或者接口名(){  //方法重写  @Override   publicvoidmethod(){    //执行语句  }};匿名内部类只能使用一次,用于创建一次性......
  • lambda匿名函数使用场景举例
    lambda函数是Python中的一种简洁的匿名函数,常用于需要快速定义简单函数的场景。尽管lambda函数的功能较为有限(只能包含单个表达式),但它在很多情况下仍然非常有用。以下是一些常见的使用场景和示例:1.作为高阶函数的参数许多内置函数和库函数(如map()、filter()和sorted())......
  • 密码学初识
    咱也是学上密码学了密码?可能有人要说:啊!这个我懂!不就是账号密码什么的嘛可能还有人说:啊!这个我懂!我还会背摩斯密码呢!但是,“密码学”研究的主要是加密与解密的过程它这个“密码”指的不是寻常说的password(口令),而是cryptography历史上,密码学经过了从古典到近代再到现代的发......
  • 走进C++——初识与探索
    一.C++发展历史  C++的起源可以追溯到1979年,当时BjarneStroustrup(本贾尼·斯特劳斯特卢普)在⻉尔实验室从事计算机科学和软件⼯程的研究⼯作。⾯对项⽬中复杂的软件开发任务,特别是模拟和操作系统的开发⼯作,他感受到了现有语⾔(如C语⾔)在表达能⼒、可维护性和可扩展性......
  • C语言程序设计(初识C语言后部分)
    晴天也会突然下暴雨,温柔的人也会不开心。二十一,实用调试技巧1.什么是bug?2.调试是什么?有多重要?3.debug和release的介绍4.vs环境调试介绍5.如何写出好(易于调试)的代码6.编程常见的错误1.什么是bug?就是使计算机程序或者计算机硬件出现问题,不能正常运行的地方称为bug(缺陷......
  • Java Lambda 表达式为何无法抛出检查型异常?——函数式接口的限制解析
    JavaLambda表达式为何无法抛出检查型异常?——函数式接口的限制解析假设场景我们需要将一组Employee对象保存到文件中,这可以通过ObjectOutputStream序列化员工对象实现。我们利用forEach方法遍历员工列表,并调用writeObject()方法序列化数据。然而,writeObject()会抛出......