我是编程新手,我注意到一个反复出现的模式是我必须在while
循环中使用的频繁否定,例如while (!isEmpty())
如果有一个“直到”循环,例如做某事直到条件为真,这不是更好的性能吗?我确实意识到否定发生在寄存器上并且速度非常快,但看起来仍然可以避免。
或者也许汇编语言的某些东西使得使用当前建立的方法更可取,即使它经常需要否定?
我是编程新手,我注意到一个反复出现的模式是我必须在while
循环中使用的频繁否定,例如while (!isEmpty())
如果有一个“直到”循环,例如做某事直到条件为真,这不是更好的性能吗?我确实意识到否定发生在寄存器上并且速度非常快,但看起来仍然可以避免。
或者也许汇编语言的某些东西使得使用当前建立的方法更可取,即使它经常需要否定?
否定很可能不会以需要任何时间的方式明确发生。
首先,天真的“while”实现在 x86 上看起来像这样
_loophead:
call _isEmpty
test eax, eax ; return value is in eax
jnz _loopend ; break out of loop if condition is not zero
... ; loop body here
jmp _loophead
_loopend:
那里没有实际的否定,只是jnz
“如果不是零就跳跃”。什么不是零?影响“标志”的最后一件事 - 上面的测试测试isEmpty()
.
一个更好的“while”实现(因为每次迭代只需要 1 个分支)看起来像
jmp _looptest
_loopstart:
... ; loop body
_looptest:
call _isEmpty
test eax, eax
jz _loopstart ; continue loop if condition is zero
否定,当它存在时,不需要额外的时间/指令/空间。许多其他处理器也是如此。
此外,如果_isEmpty
可以内联,则条件很可能甚至不会真正存在于寄存器中,它将成为标志状态的一部分(特殊寄存器中的单个位)。诸如“布尔值是 0 或 1 的整数”之类的东西是概念语义的一部分,并且通常在实际实现中被优化。你通常不需要那个 0/1 值——大多数时候你要做的第一件事就是把它放回标志寄存器中,这样你就可以在它上面分支。
即使是非常早期的 C 编译器也特别努力将“用作条件的布尔”编译为比从中生成 0/1 整数更有效的代码。