【发布时间】:2017-03-02 09:53:25
【问题描述】:
我想知道我的编译器对以下代码做了什么
void design_grid::design_valid()
{
auto valid_idx = [this]() {
if ((row_num < 0) || (col_num < 0))
{
return false;
}
if ((row_num >= this->num_rows) || (col_num >= this->num_rows))
{
return false;
}
return true;
}
/* some code that calls lambda function valid_idx() */
}
如果我反复调用上面的类成员函数(design_grid::design_valid),那么当我的程序每次遇到valid_idx的创建时究竟会发生什么?编译器是否在编译时将稍后调用的代码内联,以便在遇到 valid_idx 的创建时实际上不执行任何操作?
更新
下面是一段汇编代码。如果这有点太阅读了,我稍后会发布另一批彩色代码,以说明哪些部分是哪些部分。 (目前没有一个很好的方法来和我一起为代码段着色)。另请注意,我已经更新了我的成员函数和上面的 lambda 函数的定义,以反映它在我的代码中的真正名称(因此,在汇编语言中)。
无论如何,似乎 lambda 是与主函数分开定义的。 lambda 函数由下面的_ZZN11design_grid12design_validEvENKUliiE_clEii 函数表示。在此函数的正下方,依次启动由_ZN11design_grid12design_validEv 表示的外部函数(design_grid::design_valid)。稍后在_ZN11design_grid12design_validEv 中,调用_ZZN11design_grid12design_validEvENKUliiE_clEii。进行调用的这一行看起来像
call _ZZN11design_grid12design_validEvENKUliiE_clEii #
如果我错了,请纠正我,但这意味着编译器将 lambda 定义为 design_valid 函数之外的普通函数,然后在应该的时候将其作为普通函数调用?也就是说,它不是每次遇到声明lambda函数的语句时都创建一个新对象吗?我可以在该特定位置看到的 lambda 函数的唯一跟踪是在第二个函数中注释为 # tmp85, valid_idx.__this 的行中,就在函数开始时重新调整基指针和堆栈指针之后,但这只是一个简单的movq 操作。
.type _ZZN11design_grid12design_validEvENKUliiE_clEii, @function
_ZZN11design_grid12design_validEvENKUliiE_clEii:
.LFB4029:
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
movq %rdi, -8(%rbp) # __closure, __closure
movl %esi, -12(%rbp) # row_num, row_num
movl %edx, -16(%rbp) # col_num, col_num
cmpl $0, -12(%rbp) #, row_num
js .L107 #,
cmpl $0, -16(%rbp) #, col_num
jns .L108 #,
.L107:
movl $0, %eax #, D.81546
jmp .L109 #
.L108:
movq -8(%rbp), %rax # __closure, tmp65
movq (%rax), %rax # __closure_4(D)->__this, D.81547
movl 68(%rax), %eax # _5->D.69795.num_rows, D.81548
cmpl -12(%rbp), %eax # row_num, D.81548
jle .L110 #,
movq -8(%rbp), %rax # __closure, tmp66
movq (%rax), %rax # __closure_4(D)->__this, D.81547
movl 68(%rax), %eax # _7->D.69795.num_rows, D.81548
cmpl -16(%rbp), %eax # col_num, D.81548
jg .L111 #,
.L110:
movl $0, %eax #, D.81546
jmp .L109 #
.L111:
movl $1, %eax #, D.81546
.L109:
popq %rbp #
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE4029:
.size _ZZN11design_grid12design_validEvENKUliiE_clEii,.-_ZZN11design_grid12design_validEvENKUliiE_clEii
.align 2
.globl _ZN11design_grid12design_validEv
.type _ZN11design_grid12design_validEv, @function
_ZN11design_grid12design_validEv:
.LFB4028:
.cfi_startproc
pushq %rbp #
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp #,
.cfi_def_cfa_register 6
pushq %rbx #
subq $72, %rsp #,
.cfi_offset 3, -24
movq %rdi, -72(%rbp) # this, this
movq -72(%rbp), %rax # this, tmp85
movq %rax, -32(%rbp) # tmp85, valid_idx.__this
movl $0, -52(%rbp) #, active_count
movl $0, -48(%rbp) #, row_num
jmp .L113 #
.L128:
movl $0, -44(%rbp) #, col_num
jmp .L114 #
.L127:
movl -44(%rbp), %eax # col_num, tmp86
movslq %eax, %rbx # tmp86, D.81551
【问题讨论】:
-
编译并检查程序集?
-
godbolt.org/g/mKOiUc -- 这将取决于你在那里放了什么。在这个简单的例子中,整个事情都被优化了。
-
@KonradKapp 因为这对问题无关紧要,并且不需要任何人解释投票。如果需要,您可以发表评论,但它不属于问题。
-
看看这个来自 Jason Turner 的关于 lambdas 的精彩会议 -> youtube.com/watch?v=_CbBfuQQQI8
-
@NathanOliver 我在上面贴了一些程序集,如果你有兴趣的话
标签: c++ performance lambda