Большая часть этого вопроса будет зависеть от того, что A
, B
и C
на самом деле (и компилятор будет оптимизировать его, как показано ниже). Простые типы, определенно не стоит беспокоиться. Если это какие-то «объекты с большим количеством чисел» или какой-то сложный тип данных, для которого требуется 1000 инструкций для каждого, «это true
или нет», тогда будет большая разница, если компилятор решит сделать другой код.
Как всегда, когда дело доходит до производительности: Измерьте в своем собственном коде, используйте профилирование, чтобы определить, где код тратит БОЛЬШЕ времени, а затем измерять с изменениями этого кода. Повторяйте до тех пор, пока он не запустится достаточно быстро [независимо от того, что] и/или ваш менеджер говорит вам прекратить возиться с кодом. Как правило, однако, если он не является ДЕЙСТВИТЕЛЬНО высокой областью трафика кода, не будет иметь большого значения переупорядочить условия в if-statement, это общий алгоритм, который в наибольшей степени влияет на общий случай.
Если мы предположим, A, B и C являются простыми типами, такими как int
, мы можем написать код для исследования:
extern int A, B, C;
extern void UpdateData();
extern void ResetData();
void func1()
{
if (A && B && C) {
UpdateData();
} else if (A && B){
ResetData();
}
}
void func2()
{
if (A && B) {
if (C) {
UpdateData();
} else {
ResetData();
}
}
}
GCC 4.8.2 с учетом этого, с -O1 производит этот код:
_Z5func1v:
cmpl $0, A(%rip)
je .L6
cmpl $0, B(%rip)
je .L6
subq $8, %rsp
cmpl $0, C(%rip)
je .L3
call _Z10UpdateDatav
jmp .L1
.L3:
call _Z9ResetDatav
.L1:
addq $8, %rsp
.L6:
rep ret
_Z5func2v:
.LFB1:
cmpl $0, A(%rip)
je .L12
cmpl $0, B(%rip)
je .L12
subq $8, %rsp
cmpl $0, C(%rip)
je .L9
call _Z10UpdateDatav
jmp .L7
.L9:
call _Z9ResetDatav
.L7:
addq $8, %rsp
.L12:
rep ret
другими словами: никакой разницы
Использование лязг ++ 3.7 (как о е около 3 недель назад) с -O1 дает это:
_Z5func1v: # @_Z5func1v
cmpl $0, A(%rip)
setne %cl
cmpl $0, B(%rip)
setne %al
andb %cl, %al
movzbl %al, %ecx
cmpl $1, %ecx
jne .LBB0_2
movl C(%rip), %ecx
testl %ecx, %ecx
je .LBB0_2
jmp _Z10UpdateDatav # TAILCALL
.LBB0_2: # %if.else
testb %al, %al
je .LBB0_3
jmp _Z9ResetDatav # TAILCALL
.LBB0_3: # %if.end8
retq
_Z5func2v: # @_Z5func2v
cmpl $0, A(%rip)
je .LBB1_4
movl B(%rip), %eax
testl %eax, %eax
je .LBB1_4
cmpl $0, C(%rip)
je .LBB1_3
jmp _Z10UpdateDatav # TAILCALL
.LBB1_4: # %if.end4
retq
.LBB1_3: # %if.else
jmp _Z9ResetDatav # TAILCALL
.Ltmp1:
цепное и в func1 от лязга может быть полезным, но это, вероятно, такая небольшая разница, что вы должны сосредоточиться на том, что имеет смысл от логическая перспектива кода.
В заключение: Не стоит
Higher оптимизация в г ++ делает это не сделать то же оптимизацию tailcall, что лязг делает, иначе никакой разницы.
Однако, если мы делаем A
, B
и C
во внешние функции, которые компилятор не может «понять», то мы получим разницу:
_Z5func1v: # @_Z5func1v
pushq %rax
.Ltmp0:
.cfi_def_cfa_offset 16
callq _Z1Av
testl %eax, %eax
je .LBB0_3
callq _Z1Bv
testl %eax, %eax
je .LBB0_3
callq _Z1Cv
testl %eax, %eax
je .LBB0_3
popq %rax
jmp _Z10UpdateDatav # TAILCALL
.LBB0_3: # %if.else
callq _Z1Av
testl %eax, %eax
je .LBB0_5
callq _Z1Bv
testl %eax, %eax
je .LBB0_5
popq %rax
jmp _Z9ResetDatav # TAILCALL
.LBB0_5: # %if.end12
popq %rax
retq
_Z5func2v: # @_Z5func2v
pushq %rax
.Ltmp2:
.cfi_def_cfa_offset 16
callq _Z1Av
testl %eax, %eax
je .LBB1_4
callq _Z1Bv
testl %eax, %eax
je .LBB1_4
callq _Z1Cv
testl %eax, %eax
je .LBB1_3
popq %rax
jmp _Z10UpdateDatav # TAILCALL
.LBB1_4: # %if.end6
popq %rax
retq
.LBB1_3: # %if.else
popq %rax
jmp _Z9ResetDatav # TAILCALL
Здесь мы видим разницу между func1
и func2
, где func1
будет звонить A
и B
дважды - поскольку компилятор не может предположить, что вызов этих функций ONCE будет делать то же самое, что и вызов дважды. [Учтите, что функции A
и B
могут считывать данные из файла, вызывая rand
или что-то еще, результат НЕ НАЗЫВАЕТ эту функцию, так как программа ведет себя по-разному.
(В данном случае я только разместил код лязг, но г ++ производит код, который имеет тот же результат, но несколько иной порядок различных кусков кода)
Вы можете посмотреть на скомпилированный код, но моя ставка будет будь они компилируются в один и тот же код. Это также пахнет микро-оптимизацией, просто напишите, что наиболее читаемо. – CoryKramer
... если A или B не связаны с оценкой, которая может иметь побочные эффекты. – nneonneo
Почему это помечено C? C не имеет методов. – m0skit0