C++中lambda的实现(2)

之前写了一篇C++中的lambda的实现(1),从汇编语言的角度来分析了一下non-mutable lambda的实现方式。这篇文章主要介绍一下mutable lambda的实现方式。而这篇文章中有比较详细的lambda语法示例

实验用gcc版本4.7.2,据说4.5以前的gcc不能支持C++11中的lambda。

C++源码

1 //lambda.cpp
2 #include <iostream>
3 using namespace std;
4 int main(){
5 int a,b;
6 a = 1;
7 b = 2;
8 auto f = [&a, &b](int c)->int{ a++; b++; return a+b+c;}; //创建一个lambda表达式,’&’表示a, b以引用传递,
//可以被修改,并且修改会反映到main中的a、b
9 cout<<result= <<f(3)<<endl;
10 cout<<a= <<a<<endl;
11 cout<<b= <<b<<endl;
12 return 0;
13 }

编译运行

g++ -std=c++0x lambda.cpp –o lambda
.
/lambda
result
= 8
a
= 2
b
= 3

从结果来看,lamba表达式执行之后,a、b的值成功地被修改了。

下面这一段是main函数6-8行以及f(3)对应的汇编代码,同上次分析的一样,lambda在C++中编译成一个函数。

1 80487ea: c7 44 24 10 01 00 00 movl $0x1,0x10(%esp) # a=1
2 80487f1: 00
3 80487f2: c7 44 24 14 02 00 00 movl $0x2,0x14(%esp) # b=2
4 80487f9: 00
5 80487fa: 8d 44 24 10 lea 0x10(%esp),%eax
6 80487fe: 89 44 24 18 mov %eax,0x18(%esp) #0x18(%ebp)(记为ref_a)中存放了a的地址
7 8048802: 8d 44 24 14 lea 0x14(%esp),%eax
8 8048806: 89 44 24 1c mov %eax,0x1c(%esp) #0x1c(%ebp)(记为ref_b)中存放了b的地址
9 804880a: c7 44 24 04 03 00 00 movl $0x3,0x4(%esp) #将f(3)中的参数3放在栈上
10 8048811: 00
11 8048812: 8d 44 24 18 lea 0x18(%esp),%eax
12 8048816: 89 04 24 mov %eax,(%esp) #将ref_a的地址放在栈上
13 8048819: e8 8e ff ff ff call 80487ac <_ZZ4mainENKUliE_clEi> #调用lambda对应的函数

下面这一段是lambda函数所对应的汇编代码

80487ac: 55 push %ebp
8
0487ad: 89 e5 mov %esp,%ebp
8
0487af: 8b 45 08 mov 0x8(%ebp),%eax #取出上面一段汇编代码中12行所存的ref_a的地址
8
0487b2: 8b 00 mov (%eax),%eax #取出ref_a的值,也就是a的地址
8
0487b4: 8b 10 mov (%eax),%edx #取出a的值到edx
8
0487b6: 83 c2 01 add $0x1,%edx # a++
8
0487b9: 89 10 mov %edx,(%eax) #存回a,注意这个时候是存回到了main函数栈上的a里面
8
0487bb: 8b 45 08 mov 0x8(%ebp),%eax #取出ref_a的地址
8
0487be: 8b 40 04 mov 0x4(%eax),%eax #ref_a和ref_b是紧挨着存储的
#这一条指令取出ref_b的值,也就是b的地址
8
0487c1: 8b 10 mov (%eax),%edx #取出b的值,放入edx
8
0487c3: 83 c2 01 add $0x1,%edx # b++
8
0487c6: 89 10 mov %edx,(%eax) #存回b
8
0487c8: 8b 45 08 mov 0x8(%ebp),%eax
8
0487cb: 8b 00 mov (%eax),%eax
8
0487cd: 8b 10 mov (%eax),%edx #再取a的值,放在edx
8
0487cf: 8b 45 08 mov 0x8(%ebp),%eax
8
0487d2: 8b 40 04 mov 0x4(%eax),%eax
8
0487d5: 8b 00 mov (%eax),%eax
8
0487d7: 01 c2 add %eax,%edx #edx = a+b
8
0487d9: 8b 45 0c mov 0xc(%ebp),%eax #取出上一段汇编中第9行放在站上的参数3
8
0487dc: 01 d0 add %edx,%eax #eax= a+b+c,而函数返回值放在eax中
8
0487de: 5d pop %ebp
8
0487df: c3 ret

从上面的汇编分析来看,gcc在实现mutable lambda的时候,将lambda的代码编译为函数,将capture list中的可写变量的地址通过一些手段传入到lambda实现函数中。对比之下,non-mutable的lambda则将capture list中变量的值复制一遍,再将复制出来的变量的地址通过一些手段传入lambda实现函数。

本文链接



You must enable javascript to see captcha here!

Copyright © All Rights Reserved · Green Hope Theme by Sivan & schiy · Proudly powered by WordPress

无觅相关文章插件,快速提升流量