nt a = 0xB;
mov dword ptr [ebp-8],0Bh
auto lambda = [=]{
int s = a;
};
lea eax,[ebp-8]
push eax
lea ecx,[ebp-14h]
call 010E1BE0
lambda();
lea ecx,[ebp-14h]
call 010E1C20
return 0;
发现还call了一个带参函数:
上面的操作相当于下面的伪代码:
call 010E1BE0( &a , this); //当然,this并不是作为参数传入的,这里只是方便理解
可以预见,010E1BE0函数的作用应该是拷贝a,并让this指向a,空口无凭,进去看看:
push ebp
mov ebp,esp
sub esp,0CCh
push ebx
push esi
push edi
push ecx
lea edi,[ebp+FFFFFF34h]
mov ecx,33h
mov eax,0CCCCCCCCh
rep stos dword ptr es:[edi]
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]
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
ret 4
前后的代码按部就班,主要是中间:
关于[ebp+8]:还记得传入该函数的参数&a吗?没错,[ebp+8]保存的是就是&a。
简单翻译一下这个函数的意思:
fun(&a,this);
int* fun(int* in,int* this)
{
*this = *in;
return this;
}
注意这里的this传递其实是通过寄存器的方式。
好了,说了半天,刚才那个问题,差不多也知道答案了。
调用闭包函数前,“捕获者”this指针被放在main中,并对其指向的内存块拷贝闭包中要用到的变量值,调用时,this通过寄存器送入闭包中,闭包通过this访问外层作用域(这里是main)的已捕获对象(这里是a)。
可见,如果闭包要按值捕获main中多个变量,那么事先要调用一个复制函数,依次复制所有要用的变量,然后通过this寻址访问main中变量的副本,而不是把所有变量拷贝到闭包的栈空间内。
上面说的都是最简单的形式,也即:[=]{ },之后的文章将分析更复杂的lambda表达式。