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

作者:无名    it人知识库   2020-09-14 00:00:00

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表达式进行分析。


it人知识库 原文链接:https://m.itpeo.net/15310/3710233.html

Tag:特性中的匿名函数表达式汇编实现分析



我要分享:

  • 微信
  • QQ好友
  • QQ空间
  • 新浪微博


热门推荐

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

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

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

[zt]Ajax 和 XML: 五种常见 Ajax 模式

[zt]Ajax 和 XML: 五种常见 Ajax 模式

可立即使用这些非常有用的 Ajax 设计模式 ... ...

MDA:Jean网站上的定义和资源

MDA:Jean网站上的定义和资源

继续纠缠MDA的定义 转自 http://www.sciences.univ-nantes.fr/info/lrsg... ...

Spring Framework 4.0M1 & 3.2.3 发布了[翻译]

Spring Framework 4.0M1 & 3.2.3 发布了[翻译]

今天早上去SpringSource官网,发现Spring Framework 4.0发布了,我认为最重要的两个特性... ...

简单说一下Jfinal Model静态dao对象误用的问题

简单说一下Jfinal Model静态dao对象误用的问题

   最近有很多jfinal的使用者在误用model静态dao,这里简单的说一下这个问题, @... ...

职业生涯第二年回顾(2011.2~2012.2)

职业生涯第二年回顾(2011.2~2012.2)

 算不上什么工作总结和技术总结,只是大致回顾这1年记忆中的事情。    一... ...

使用import简化spring的配置文件 (转载)

使用import简化spring的配置文件 (转载)

Spring中用import导入配置文件 原文地址:使用import简化spring的配置文件 (转载)作者:瓦砾... ...

每天十分钟,十二天入门Python(十)

每天十分钟,十二天入门Python(十)

# __str__() class Dog(object):     de... ...

JQuery:deferred对象的方法

JQuery:deferred对象的方法

(1) $.Deferred() 生成一个deferred对象。 (2) deferred.done() 指... ...

Maven的安装及与eclipse或MyEclipse的关联

Maven的安装及与eclipse或MyEclipse的关联

apache-Maven的下载就不说了,其安装与JDK的安装几乎类似。当然使用Maven的前提是已经安装好了JD... ...

怎么在HiWork中注册团队及添加成员

怎么在HiWork中注册团队及添加成员

周三,天气较热,各位注意身体,多饮水。 使用HiWork,首先要进行团队创建以及成员添加,这样才能愉快地... ...

linux wineQQ与win7QQ共用聊天记录

linux wineQQ与win7QQ共用聊天记录

首先挂载win7硬盘,挂载方法就不介绍了。 然后点开QQ的设置  -> 文件管理 -&g... ...

Clustrix Sierra关系数据库集群

Clustrix Sierra关系数据库集群

Clustrix的Sierra数据库集群引擎是一个share-nothing架构的可伸缩关系数据库集群。官... ...

Android圆了Linux桌面之梦

Android圆了Linux桌面之梦

Google开源主管Chris DiBona在采访中称,Android圆了Linux桌面之梦。 DiBona表示,... ...

系统管理构架

系统管理构架

1. 登录系统(VPN+ssh)。 为了保护系统,登录系统应该有审计,有记录。并且,普通用户只不能在登录... ...

swing 消息框 joptionpane

swing 消息框 joptionpane

4.消息弹出窗口 import javax.swing.JFrame; import javax.sw... ...

swing 消息框 joptionpane

swing 消息框 joptionpane

1.使用JOptionPane提示用户确认 import javax.swing.JOptionPan... ...

Quartz之SimpleTrigger

Quartz之SimpleTrigger

SimpleTrigger: 它只能用于指定任务在一个特定时间内运行,可指定任务的重复(时间,次数)与间隔(时间,次数)... ...

人力资源主管的素质要求

人力资源主管的素质要求

作者:佚名 现代企业的人力资源管理的总趋势是以人为本,本着认识人、尊重人、开发人、激励人的观念,把人看成是一种... ...

C++xml文件操作 CMarkup学习方法说明

C++xml文件操作 CMarkup学习方法说明

   最近正在研究C++下的XML分析工具CMarkup。初次和XML相遇是基于C#对XML的... ...

最新IT资讯

必填

◎已有 0 人评论


电脑版

版权所有:IT人知识库 m.itpeo.net

返回顶部

本网站部分内容来自互联网,版权归原作者所有,文章内容仅代表原作者个人观点,如有侵权请联系我们删除