2019独角兽企业重金招聘Python工程师标准>>>

C++11新特性中的匿名函数Lambda表达式的汇编实现分析(一)

首先,让我们来看看以&方式进行变量捕获,同样没有参数和返回。

int main()
{int a = 0xB;auto lambda = [&]{a = 0xA;};lambda();return 0;
}

闭包中将main中a变量改写为0xA。

main中的关键汇编代码:

int a = 0xB;mov         dword ptr [ebp-8],0Bh  auto lambda = [&]{a = 0xA;};lea         eax,[ebp-8]  push        eax  lea         ecx,[ebp-14h]  call        002D1BE0  lambda();lea         ecx,[ebp-14h]  call        002D1C20  return 0;

同样的,进入闭包前要调用一个拷贝函数。

002D1BE0 内:

 pop         ecx  mov         dword ptr [ebp-8],ecx  mov         eax,dword ptr [ebp-8]  mov         ecx,dword ptr [ebp+8]  mov         dword ptr [eax],ecx  mov         eax,dword ptr [ebp-8]  pop         edi  pop         esi  pop         ebx  mov         esp,ebp  pop         ebp  ret         4

和前面一篇文章中的代码基本一致,但是有两个地方不同,

上文写到:

pop         ecx

mov         dword ptr [ebp-8],ecx

mov         eax,dword ptr [ebp-8]

mov         ecx,dword ptr [ebp+8]

 mov         edx,dword ptr [ecx]  

 mov         dword ptr [eax],edx

mov         eax,dword ptr [ebp-8]

注意黑体部分,若采用[=]的捕获方式,那么将通过寄存器edx拷贝原变量的值;

若采用[&]方式,则直接通过ecx拷贝原变量的地址,而不取出值。

闭包内:

 pop         ecx  mov         dword ptr [ebp-8],ecx  a = 0xA;mov         eax,dword ptr [ebp-8]  mov         ecx,dword ptr [eax]  mov         dword ptr [ecx],0Ah  };pop         edi  pop         esi  pop         ebx  mov         esp,ebp  pop         ebp  ret

对a进行赋值,直接是:

*this = 0xA;

因为事先this就取到了a的地址。

可以发现,按引用捕获实际上就如同函数参数传递引用,传递的是一个地址值,而不创建对象副本(可以和上一篇文中的内容比较)。

C++11标准中对Lambda表达式的捕获内容还有一些特定支持,比如可以以指定的方式捕获指定的变量:

int main()
{int a = 0xB;bool b = true;auto lambda = [&a,b]{a = b;};lambda();return 0;
}

上面的代码对a进行引用捕获,对b按值捕获。根据前面分析的结果,可以预见,a的地址和b的值将被拷贝以供闭包函数使用。

int a = 0xB;mov         dword ptr [ebp-8],0Bh  bool b = true;mov         byte ptr [ebp-11h],1  auto lambda = [&a,b]{a = b;};lea         eax,[ebp-11h]  push        eax  lea         ecx,[ebp-8]  push        ecx  lea         ecx,[ebp-24h]  call        00222060  lambda();lea         ecx,[ebp-24h]  lambda();call        00221C20  return 0;

调用Lambda之前,先调用复制函数,传入两个参数,&a和&b,而this被放在main的[ebp-24h]中。

复制函数或者叫准备函数:

 pop         ecx  mov         dword ptr [ebp-8],ecx  mov         eax,dword ptr [ebp-8]  mov         ecx,dword ptr [ebp+8]  mov         dword ptr [eax],ecx  mov         eax,dword ptr [ebp-8]  mov         ecx,dword ptr [ebp+0Ch]  mov         dl,byte ptr [ecx]  mov         byte ptr [eax+4],dl  mov         eax,dword ptr [ebp-8]  pop         edi  pop         esi  pop         ebx  mov         esp,ebp  pop         ebp  ret         8

[eax] 就是 *this,也即a

[eax+4] 就是 *(this+4),也即b

从内存图可以清楚的看到,a的地址被记录,b的值被复制

闭包函数内:

 pop         ecx  mov         dword ptr [ebp-8],ecx  a = b;mov         eax,dword ptr [ebp-8]  movzx       ecx,byte ptr [eax+4]  mov         edx,dword ptr [ebp-8]  mov         eax,dword ptr [edx]  mov         dword ptr [eax],ecx

b的值是从[eax+4]也即this+4中取出,而a在this中,其实就是:

*(this) = *(this+4);

可以看到闭包内通过this作为基址,对闭包外的变量进行偏移访问。

下一篇中,我将对具有参数和返回值的Lambda表达式进行分析。

转载于:https://my.oschina.net/ybusad/blog/277584

C++11新特性中的匿名函数Lambda表达式的汇编实现分析(二)相关推荐

  1. 【Kotlin】Kotlin 函数总结 ( 具名函数 | 匿名函数 | Lambda 表达式 | 闭包 | 内联函数 | 函数引用 )

    文章目录 一.函数头声明 二.函数参数 1.默认参数值 2.具名参数 三.Unit 函数 四.TODO 函数抛出异常返回 Nothing 类型 五.反引号函数名 六.匿名函数 七.匿名函数的函数类型 ...

  2. python匿名函数的作用_Python匿名函数 Lambda表达式作用

    在Python这门优美的编程语言中,支持一种有趣的语法格式(表达式),可以让我们在单行内创建一个最小的函数-python lambda匿名函数. 据说是借鉴了Lisp语言中lambda表达式,它可以使 ...

  3. 14_python基础—匿名函数lambda表达式

    文章目录 一.lambda 表达式 1.1 lambda的应用场景 1.2 lambda语法 快速入门 1.3 示例:计算a + b 1.3.1 函数实现 1.3.2 lambda实现 1.4 lam ...

  4. Scala匿名函数Lambda表达式详解

    1 前言 大家好,我是楚生辉,在未来的日子里我们一起来学习大数据相关的技术,一起努力奋斗,遇见更好的自己! 本文详细的介绍了scala的匿名函数,有需要的小伙伴可以学习~ Scala 中定义匿名函数的 ...

  5. python中的匿名函数lambda

    匿名函数 python 使用 lambda 来创建匿名函数. 所谓匿名,意即不再使用 def 语句这样标准的形式定义一个函数. lambda 只是一个表达式,函数体比 def 简单很多. lambda ...

  6. Java笔记整理五(Iterator接口,泛型,常见数据结构(栈,队列,数组,链表,红黑树,集合),jdk新特性,异常,多线程,Lambda表达式)

    Java笔记整理五 1.1Iterator接口 Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象 ...

  7. λ表达式_Java 8新特性:学习如何使用Lambda表达式,一看必懂

    我将分为两篇系列文章来描述了使用Java 8的新特性 - lambda表达式. 目录 介绍 我们为什么需要lambdas? Lambdas的语法 功能接口 方法参考 构造函数参考 可变范围 默认方法 ...

  8. 使用Java8新特性(stream流、Lambda表达式)实现多个List 的笛卡尔乘积 返回需要的List<JavaBean>

    需求分析: 有两个Long类型的集合 : List<Long> tagsIds; List<Long> attributesIds; 现在需要将这两个Long类型的集合进行组合 ...

  9. Python匿名函数——lambda表达式

    如果要定义的函数很简单,一个return语句就能搞定,可以使用lambda表达式来定义, lambda表达式的语法如下: lambda parameters: expression lambda表达式 ...

最新文章

  1. python第二天练习题
  2. 图卷积网络进行骨骼识别代码_【骨骼行为识别】2s-AGCN论文理解
  3. Flink从入门到精通100篇(八)-美团点评是如何在 Flink平台建立 实时数仓的?
  4. php 将date转换成string,php如何实现date转string
  5. Java中File类的createNewFile、mkdir与mkdirs区别
  6. ITK:两幅图像之差的绝对值
  7. windows系统内实现端口转发
  8. python爬取b站403_Python如何爬取b站热门视频并导入Excel
  9. 部署邮件服务器之间相互通信
  10. Android 下拉刷新上拉载入 多种应用场景 超级大放送(上)
  11. Palo Alto Networks下一代安全平台五大创新功能:云安全为重中之重
  12. web开发模式+三层架构与MVC
  13. 高性能mysql sakila_《高性能MySQL》读书笔记二
  14. vb代码转为c++代码_vb代码转为c++代码_VB源码转换工具(VBto Converter)
  15. iNFTnews | 元宇宙进行时:那些跑步入场的互联网大厂在如何谋篇布局?
  16. GO的lua虚拟机 gopher-lua
  17. Atlassian与DevOps 系列产品选择方案介绍
  18. centos7搭建bugzilla
  19. Java实现 LeetCode 492 构造矩形
  20. 计算机科学与技术研究机构名称,计算机科学与技术学院研究生团队获得SemEval-2021国际语义评测比赛Task 5第一名...

热门文章

  1. windows环境运行MongoDB
  2. Basic Windbg - 1. SOSBasics(再续)
  3. python日历gui_python GUI库图形界面开发之PyQt5日期时间控件QDateTimeEdit详细使用方法与实例...
  4. mvc mvp mvvm
  5. Metasploit设置HttpTrace参数技巧
  6. Xamarin图表开发基础教程(12)OxyPlot框架支持的金融图表类型
  7. iOS11开发教程(二十三)iOS11应用视图实现按钮的响应(3)
  8. Xamarin iOS项目找不到模拟器
  9. php拷贝mysql表_MySQL复制表数据或表结构到新表中
  10. 龙将加速浏览器_《看门狗:军团》即将开启预载,迅游加速器支持下载和联机加速 18183手机游戏网...