我并不完全理解这个问题的意义。似乎你在问“为什么当优化开关关闭时,编译器会产生未经优化的代码?” 这有点回答了自己的问题。
然而,我仍将试着回答一下。我认为这个问题实际上是像“是什么设计决策导致编译器发出本地变量#1的声明、存储和加载,并可被优化掉?”这样的问题。
答案是因为未经优化的代码生成旨在清晰、明确、易于调试,并鼓励JIT生成不过度收集垃圾的代码。我们为实现所有这些目标之一,对大多数进入堆栈的值,甚至是临时值,都生成本地变量。 让我们看一个更复杂的例子。假设你有:
Foo(Bar(123), 456)
我们可以生成这样的内容:
push 123
call Bar - this pops the 123 and pushes the result of Bar
push 456
call Foo
这很好,高效而且小巧,但它不符合我们的目标。它清晰明了,但由于垃圾回收器可能会变得过于积极,所以调试起来并不容易。如果Foo因某些原因实际上并没有使用它的第一个参数,那么在Foo运行之前,GC可以允许回收Bar的返回值。
在未经优化的构建中,我们将生成更像这样的内容
push 123
call Bar - this pops the 123 and pushes the result of Bar
store the top of the stack in a temporary location - this pops the stack, and we need it back, so
push the value in the temporary location back onto the stack
push 456
call Foo
现在Jitter有一个大提示,它说“嘿Jitter,即使Foo不使用它,请在本地保持它的活动状态一段时间”。
这里的一般规则是“在未经优化的构建中将所有临时值转换为本地变量”。因此,在评估“if”语句之前,我们需要评估条件并将其转换为bool类型。(当然,条件不必是bool类型;它可以是隐式可转换为bool类型的类型,或者实现了operator true/operator false对的类型。)未经过优化的代码生成器被告知“积极地将所有临时值转换为本地变量”,所以你得到的就是这样的结果。
我想在这种情况下,我们可以抑制作为“if”语句中条件的临时值,但那听起来像是“让我多做一些没有客户利益的工作”。由于我有一堆需要带来实际客户利益的工作要做,我不会改变未经优化的代码生成器,它会生成未经优化的代码,正如它应该做的那样。