假设我们有以下代码:
switch (currentChar) {
case 'G':
case 'T':
case 'M':
case ';':
case 'r':
case 'n':
doSomething();
break;
}
如果满足第一个条件(currentChar == 'G'
(,是否还会比较以下情况,或者程序直接跳到doSomething()
?
执行起来更快的是什么:开关情况,还是带有||
运算符的if?
澄清:如果满足任何条件,我希望执行doSomething
。我还知道,"G"病例将发生在99%的病例中。如果我把它放在列表的首位,我能假设它会被作为第一个进行比较吗?
如果满足第一个条件
(currentChar == 'G')
,是否还会评估以下情况,或者程序直接跳到doSomething()
?
它将立即跳转执行doSomething()
执行起来更快的是什么:开关情况,还是带有
||
运算符的if?
我认为这与任何像样的现代c++编译器都没有任何区别,并且发出的代码应该相当相同。
执行起来更快的是什么:开关情况,还是带有||运算符的if?
转到switch()
。如果您有一个设置了小值的枚举或整数,switch()
通常会创建一个跳转表。
将currentChar
与'G'
进行比较后,指令跳转到指令doSomething()
。您不能依赖案例的顺序来"优化"switch
。
请注意,比较不一定是按顺序进行的switch
可以实现为跳转表,例如:
void foo_switch(char c)
{
switch (c) {
case '0': bar0(); break;
case '1': bar1(); break;
case '2': bar2(); break;
case '3': bar3(); break;
};
}
void foo_if(char c)
{
if (c == '0') {
bar0();
} else if (c == '1') {
bar1();
} else if (c == '2') {
bar2();
} else if (c == '3') {
bar3();
}
}
void foo_table(char c)
{
if ('0' <= c && c <= '3') {
using voidFPtr = void(*)();
voidFPtr funcs[] = {&bar0, &bar1, &bar2, &bar3};
funcs[c - '0']();
}
}
关于特定代码风格的性能结果的问题几乎总是浪费时间。
以下是gcc5.3在优化通过后如何处理此代码:
test(char):
cmpb $59, %dil
je .L3
jle .L6
cmpb $77, %dil
je .L3
cmpb $84, %dil
je .L3
cmpb $71, %dil
je .L3
.L1:
rep ret
.L6:
cmpb $10, %dil
je .L3
cmpb $13, %dil
jne .L1
.L3:
jmp doSomething()
我真的认为,如果不创建一个256条目的跳转表,你就无法更快地编写任何东西,这会对缓存位置和耗尽产生影响。
如果满足第一个条件(currentChar=='G'(,则如下案例也进行了评估,或者程序直接跳到doSomething((?
它会失败,直到找到break
或到达终点。
执行起来更快的是什么:开关情况,还是带有||运算符的if?
您应该担心代码的可读性和可支持性,所以使用对您来说更可读的代码。然后,如果您对程序速度有问题,请进行优化。
为了可读性——当然这是主观的,但使用switch,您可以获得更少的详细代码,因为您不必多次重复变量名:
if( currentChar == 'G' || currentChar == 'B' || currentChar == 'C' )
所以在这种情况下我更愿意转换。
switch (currentChar) {
case 'G':
case 'T':
case 'M':
case ';':
case 'r':
case 'n':
doSomething();
break;
}
这使得如果currentChar
是G
、T
、M
、;
、r
或n
,则调用doSomething()
。使用switch
比使用普通的if
更快,因为switch
语句通常被优化为跳转表。这就是为什么开关必须在恒定的积分值上操作。
不能保证开关情况下的检查顺序。如果表达式没有副作用,也不能保证||
的执行顺序
基本上,如果唯一的区别是时间,那么基于"好像"规则,c++不会保证任何东西的顺序。
如果满足第一个条件(currentChar=="G"(,是否还会评估以下情况,或者程序直接跳到doSomething((?
在您的示例中,它将直接跳到doSomething()
。如果您不想有这种行为,那么您需要插入break
语句,如下例所示:
switch (currentChar) {
case 'G': /*things to be done */ break /* This break will take it out of switch*/;
case 'T':
case 'M':
case ';':
case 'r':
case 'n':
doSomething();
break;
}
另外,请注意,在您的示例中,不需要break
,因为它是switch语句的最后一条语句。有关switch语句的工作示例,请参阅此链接。
执行起来更快的是什么:开关情况,还是带有||运算符的if?
假设您使用的是一个不错的编译器,差异是最小的,因此可以忽略它。请参考这个So链接,以防您需要了解更多细节。
编辑以供澄清:
如果满足任何条件,我希望执行
doSomething()
。
是的,根据您的代码,即使只满足其中一个条件,也会执行doSomething()
。
我还知道,"G"病例将发生在99%的病例中。如果我把它放在列表的首位,我能假设它会被作为第一个进行比较吗?
剩下的病例将不予检查。