gpt4 book ai didi

C++ Lambda 生成的 ASM 代码

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:50:24 26 4
gpt4 key购买 nike

我有以下初始 C++ 代码:

class Lambda
{
public:
int compute(int &value){
auto get = [&value]() -> int {
return 11 * value;
};
return get();
}
};

int main(){
Lambda lambda;
int value = 77;
return lambda.compute(value);
}

使用 clang 编译(使用 -O1)生成的 ASM 以下:

main: # @main
push rax
mov dword ptr [rsp + 4], 77
mov rdi, rsp
lea rsi, [rsp + 4]
call Lambda::compute(int&)
pop rcx
ret
Lambda::compute(int&): # @Lambda::compute(int&)
push rax
mov qword ptr [rsp], rsi
mov rdi, rsp
call Lambda::compute(int&)::{lambda()#1}::operator()() const
pop rcx
ret
Lambda::compute(int&)::{lambda()#1}::operator()() const: # @Lambda::compute(int&)::{lambda()#1}::operator()() const
mov rax, qword ptr [rdi]
mov eax, dword ptr [rax]
lea ecx, [rax + 4*rax]
lea eax, [rax + 2*rcx]
ret

问题:

  1. 出现在 ASM 中的 {lambda()#1} 是什么?据我所知,它可能是一个封装函数对象(即 lambda 主体)的闭包。如果是,请确认。
  2. 是否每次触发compute() 时都会生成一个新的闭包?还是同一个实例?

最佳答案

  1. 是的,调用 lambda 函数需要生成一个闭包 [除非编译器可以推断它实际上没有被使用]

  2. 通过这种优化,每次调用都是对 compute 的调用,后者又会调用内部函数 get(),这是一个 lambda 函数在你的 compute 函数中。让编译器优化到更高的程度,对于这种情况,将优化调用 - 在我的尝试中,它将完全删除带有 -O2 的整个调用,并且只返回预先计算的常量847 - 如您所料。对于更复杂的情况,它可能会或可能不会内联 lambda 部分但保留外部调用,反之亦然。这在很大程度上取决于所涉及函数内部发生的事情的具体细节。

    需要说明的是,编译器正在按照您的要求进行操作:调用函数 compute,后者又调用函数 get

添加

    int value2 = 88;
int tmp = lambda.compute(value2);

进入原始问题中的 main 函数本质上对生成的代码产生了这种变化(在 Linux 上使用 clang++):

main:                                   # @main
pushq %rbx
subq $16, %rsp
movl $77, 12(%rsp)
## new line to set value2
movl $88, 8(%rsp)
movq %rsp, %rbx
## New line, passing reference of `value2` to lambda.compute
leaq 8(%rsp), %rsi
movq %rbx, %rdi
## Call lambda.compute
callq _ZN6Lambda7computeERi
## Same as before.
leaq 12(%rsp), %rsi
movq %rbx, %rdi
callq _ZN6Lambda7computeERi
addq $16, %rsp
popq %rbx
retq

代码生成到

关于C++ Lambda 生成的 ASM 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49294022/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com