我只是想在C/C++中的两个语句之间有任何性能差异:
情况1:
if (p==0)
do_this();
else if (p==1)
do_that();
else if (p==2)
do_these():
Run Code Online (Sandbox Code Playgroud)
案例2:
if(p==0)
do_this();
if(p==1)
do_that();
if(p==2)
do_these();
Run Code Online (Sandbox Code Playgroud)
der*_*ert 34
假设简单类型(在这种情况下,我使用int)并且没有有趣的业务(没有重新定义operator = for int),至少在AMD64上使用GCC 4.6,没有区别.生成的代码完全相同:
0000000000000000 <case_1>: 0000000000000040 <case_2>:
0: 85 ff test %edi,%edi 40: 85 ff test %edi,%edi
2: 74 14 je 18 <case_1+0x18> 42: 74 14 je 58 <case_2+0x18>
4: 83 ff 01 cmp $0x1,%edi 44: 83 ff 01 cmp $0x1,%edi
7: 74 27 je 30 <case_1+0x30> 47: 74 27 je 70 <case_2+0x30>
9: 83 ff 02 cmp $0x2,%edi 49: 83 ff 02 cmp $0x2,%edi
c: 74 12 je 20 <case_1+0x20> 4c: 74 12 je 60 <case_2+0x20>
e: 66 90 xchg %ax,%ax 4e: 66 90 xchg %ax,%ax
10: f3 c3 repz retq 50: f3 c3 repz retq
12: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 52: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
18: 31 c0 xor %eax,%eax 58: 31 c0 xor %eax,%eax
1a: e9 00 00 00 00 jmpq 1f <case_1+0x1f> 5a: e9 00 00 00 00 jmpq 5f <case_2+0x1f>
1f: 90 nop 5f: 90 nop
20: 31 c0 xor %eax,%eax 60: 31 c0 xor %eax,%eax
22: e9 00 00 00 00 jmpq 27 <case_1+0x27> 62: e9 00 00 00 00 jmpq 67 <case_2+0x27>
27: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 67: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
2e: 00 00 6e: 00 00
30: 31 c0 xor %eax,%eax 70: 31 c0 xor %eax,%eax
32: e9 00 00 00 00 jmpq 37 <case_1+0x37> 72: e9 00 00 00 00 jmpq 77 <case_2+0x37>
37: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
3e: 00 00
Run Code Online (Sandbox Code Playgroud)
case_1末尾的额外指令仅用于填充(以使下一个函数对齐).
这并不奇怪,确定p没有改变,该功能是相当基本的优化.如果p可以改变(例如,通过引用传递或指向各种do_…函数的指针,或者是引用或指针本身,那么可能存在别名)那么行为就不同了,当然生成的代码也是如此.
Mic*_*ker 21
在前一种情况下,不评估匹配的一个条件.
Waq*_*leh 12
如果别人是更快 ; 如果在最后一个之前找到匹配,那么至少跳过最后一个if语句,如果首先找到匹配,它将跳过所有其他语句.
如果是慢的话 ; 即使使用第一个if语句找到匹配项,它也将继续尝试匹配其他语句.
正如已经证明的那样……它有所不同。
如果我们谈论像这样的原始(内置)类型int,那么编译器可能足够聪明,因此它并不重要(或不重要)。但无论如何,对性能的影响很小,因为调用函数的成本比调用 a 的成本高得多if,因此如果您尝试测量它,差异可能会在噪音中消失。
然而,语义却截然不同。
当我读到第一个案例时:
if (...) {
// Branch 1
} else if (...) {
// Branch 2
}
Run Code Online (Sandbox Code Playgroud)
然后我知道无论这两个分支会做什么,都只能执行其中一个。
然而,当我读到第二个案例时:
if (...) {
}
if (...) {
}
Run Code Online (Sandbox Code Playgroud)
然后我必须想知道是否有可能两个分支都被采用,这意味着我必须仔细检查第一个分支中的代码以确定它是否可能影响第二个测试。当我最终断定事实并非如此时,我咒骂那个该死的开发人员,他懒得写那些该死的东西else,这本来可以节省我最后 10 分钟的审查时间。
所以,帮助你自己和你未来的维护者,集中精力让语义正确和清晰。
在这个主题上,有人可能会争辩说,也许这种调度逻辑可以用其他结构更好地表达,例如 aswitch或可能是map<int, void()>? (谨防后者并避免过度设计;))