“编译器资源管理器”之类的工具非常适合回答此类问题。修复代码中的错误并比较以下两个片段,我们看到它们在 -O1 和更高版本中生成相同的程序集。
void trinary(int& val, int otherVal) {
val = (val != 0) ? otherVal : 0;
}
void nontrinary(int& val, int otherVal) {
if(val != 0) {
val = otherVal;
}
else {
val = 0;
}
}
trinary(int&, int):
mov eax, DWORD PTR [rdi]
test eax, eax
mov eax, 0
cmove esi, eax
mov DWORD PTR [rdi], esi
ret
nontrinary(int&, int):
mov eax, DWORD PTR [rdi]
test eax, eax
mov eax, 0
cmove esi, eax
mov DWORD PTR [rdi], esi
ret
有趣的是,在 -O0 处,它们不会产生相同的输出。在 -O0 处,编译器用于eax
显式存储三元运算符的结果,然后eax
在返回之前复制到正确的寄存器中。非三元版本直接进行赋值。
trinary(int&, int):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov DWORD PTR [rbp-12], esi
mov rax, QWORD PTR [rbp-8]
mov eax, DWORD PTR [rax]
test eax, eax
je .L2
mov eax, DWORD PTR [rbp-12]
jmp .L3
.L2:
mov eax, 0
.L3:
mov rdx, QWORD PTR [rbp-8]
mov DWORD PTR [rdx], eax
nop
pop rbp
ret
nontrinary(int&, int):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov DWORD PTR [rbp-12], esi
mov rax, QWORD PTR [rbp-8]
mov eax, DWORD PTR [rax]
test eax, eax
je .L5
mov rax, QWORD PTR [rbp-8]
mov edx, DWORD PTR [rbp-12]
mov DWORD PTR [rax], edx
jmp .L7
.L5:
mov rax, QWORD PTR [rbp-8]
mov DWORD PTR [rax], 0
.L7:
nop
pop rbp
ret