当前位置: 首页 > news >正文

【lambda函数】lambda()函数

lambda()

  • lambda()语法
    • 捕捉列表
      • mutable
    • lambda 底层原理
      • 函数对象与lambda表达式

lambda()语法

lambda表达式书写格式:

[capture-list] (parameters) mutable -> return-type{ statement
}

咱们一个个来解释:
[capture-list] :捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据 [] 来判断接下来的代码是否为lambda函数,捕捉列表能够捕捉上下文中的变量供lambda函数使用。不能省略

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

mutable: 默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。

-> return-type:返回值类型,用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。

statement:函数体,在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。不可省略

因此,把可以省略的都省略掉,最那简单的lambda函数是 []{} ,该 lambda 表达式没有任何意义。该lambda函数不能做任何事情。

接下来写一个lambda函数:

auto add = [](int x, int y)->int{return x + y;};

lambda表达式实际上可以理解为无名函数,该函数无法直接调用,如果想要直接调用,可借助auto将其赋值给一个变量。
调用:

	//第一种add(10, 20);//第二种[](int x, int y)->int {return x + y;}(10, 20);

可以看出,lambda函数和普通函数在组成和调用上都很相似。参数列表,返回值,函数体都不在多叙述。

捕捉列表

捕捉列表描述了上下文中那些数据可以被lambda使用。

如:

    int a = 10;int b = 20;auto add = [a,b]() {return a + b ;};

直接捕捉了 a b 变量,且是传值捕捉,lambda函数体内的a, b变量,只是外边 a b 的一份拷贝。且默认无法修改。
在这里插入图片描述
要想修改,可以使用 mutable 进行修饰。

mutable

如:

auto add = [a, b]() mutable{a = 20;return a + b;};

在这里插入图片描述

就不会报错,但因为是传值,所以lambda 函数内部 a的变化,无法影响外部的a变量。

mutable 用的比较少。

当然,lambda函数 和普通函数一样,捕捉列表,可以传值捕捉,也可以传引用捕捉。

    int x = 10;int y = 20;//捕捉列表//传引用   参数列表auto fun1 = [](int& x, int& y) {int tmp = x;x = y;y = x;};// 传引用捕捉   auto fun2 = [&x,&y]() {int tmp = x;x = y;y = x;};//对上下文所有变量进行传引用捕捉auto fun3 = [&]() {x = y;};//对除y以外的所有变量传引用捕捉,y传值捕捉auto fun4 = [&, y] {;};//对y进行传值捕捉,对其余变量进行传引用捕捉auto fun5 = [=, &y] {;};

lambda 底层原理

看如下代码:

int main()
{int a = 10;int b = 20;auto add = [a, b]() mutable{a = 20;return a + b;};cout << typeid(add).name() << endl;cout << sizeof(add) << endl;return 0;
}

lambda 函数的类型变量是什么呢?
lambda 类型的大小又是多少呢?

在这里插入图片描述

从运行结果上来看,其大小为一,类型大致为一个类,具体是什么我们现在也不清楚。

函数对象与lambda表达式

函数对象,又称为仿函数,即可以想函数一样使用的对象,就是在类中重载了operator()运算符的类对象。

//仿函数
class math {
public:int operator() (int x, int y){return x + y;}
};int main()
{int a = 10;int b = 20;//仿函数对象math m;//lambda函数auto add = [](int a,int b) {return a + b;};m(a, b);add(a, b);return 0;
}

我们从反汇编上来看,
仿函数底层代码,调用了 重载的 ()
在这里插入图片描述

lambda() 函数的底层:
在这里插入图片描述
我们也可以看出,也是调用了一个lambda 类里的重载的()

不妨看出,lambda()函数的底层就是一个重载了()的空类。

所以就可以知道,lambda类型的大小为1了:

因为,它的底层是一个空类,是一个仿函数。

至于它的类型,如图:
在这里插入图片描述

也就是,上图是 lambda_UUID
UUID 是 通用唯一识别码(Universally Unique Identifier)的缩写,是通过一种特殊的算法计算出来的具有唯一识别信息的 数据。

也就是说,每一个lambda()对象的类型都不一样。
也就不存在不同lambda()对象相互赋值的情况。

结语
本次的博客就到这了。

我是Tom-猫,
如果觉得有帮助的话,记得
一键三连哦ヾ(≧▽≦*)o。

咱们下期再见。

在这里插入图片描述

http://www.lryc.cn/news/94527.html

相关文章:

  • ThreeJs CSS3DObject 点击失效问题
  • 飞书深诺、恒生面试(部分)(未完全解析)
  • Spring Cloud Config: 了解、原理和使用
  • 基于图的路径规划算法对比
  • SQL Server 索引
  • java抽奖
  • 【springboot+云计算】B/S医院信息管理系统源码(云HIS)
  • go 读写 excel 读取 txt 繁体中文转码
  • docker网卡的IP地址修改
  • python与深度学习——基础环境搭建
  • Django实现简单的音乐播放器 2
  • OpenCV 入门教程:图像读取和显示
  • 什么是GPT?
  • 如何通过浏览器配置哪些网页不走代理服务器,Lantern开启后部分网页打不开了
  • Redis常见面试题
  • 应用零信任原则:案例研究和现场经验教训
  • RabbitMQ系列(14)--Topics交换机的简介与实现
  • 解决PyInstaller打包selenium脚本时弹出driver终端窗口
  • 基于卷积神经网络VGG的猫狗识别
  • mysql查询语句练习总结(涵盖所有sql语法)
  • TypeScript 中 any、unknown、never 和 void 有什么区别?
  • 算法Day60 | 84.柱状图中最大的矩形,刷题总结
  • python实现pdf转换为word文档,尽量保持格式不变
  • TCP / IP 网际层的 4 个重要协议
  • MySQL阶段DAY20(附笔记)
  • 考场作弊行为自动抓拍告警算法 yolov7
  • 在Linux中安装RabbitMQ
  • electron 单个实例控制以及日志输出
  • 基于matlab使用AprilTag标记进行相机校准(附源码)
  • 计算机网络————运输层