C ++开关语句评估

时间:2016-06-24 13:33:00

标签: c++ if-statement switch-statement conditional

假设我们有以下代码:

switch (currentChar) {
    case 'G':
    case 'T':                   
    case 'M':
    case ';':                       
    case '\r':                      
    case '\n':  
        doSomething();      
        break;
}

如果满足第一个条件(currentChar == 'G'),还会比较以下情况,或者程序直接跳到doSomething()

执行速度会更快:switch-case,还是if ||运算符?

澄清: 如果满足任何条件,我希望doSomething被执行。我也知道' G'案件将发生在所有案件的99%。如果我把它放在列表的顶部,我可以假设它将作为第一个进行比较吗?

9 个答案:

答案 0 :(得分:3)

  

如果满足第一个条件(currentChar == 'G'),还会评估以下情况,或者程序直接跳到doSomething()

它会立即跳转到执行doSomething()

  

执行速度会更快:switch-case,还是if ||运算符?

我认为它不会对任何体面的现代c ++编译器产生任何影响,并且发出的代码应该相同。

答案 1 :(得分:1)

  

执行速度会更快:switch-case,或带有||的if操作

转到switch()。如果你有一个设置值很小的枚举或整数,switch()通常会创建一个跳转表。

答案 2 :(得分:1)

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']();
    }
}

答案 3 :(得分:1)

关于特定代码风格的性能结果的问题几乎总是浪费时间。

以下是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条目跳转表的情况下更快地编写任何内容,这会在缓存局部性和耗尽方面产生影响。

答案 4 :(得分:0)

  

如果满足第一个条件(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语句的工作示例,请参阅this链接。

  

执行速度会更快:switch-case,或带有||的if操作

假设您正在使用一个不错的编译器,差异是最小的,因此可以忽略它。如果您需要了解更多细节,请参阅this所以链接。

编辑以供澄清

  

如果满足任何条件,我希望doSomething()被执行。

是的,根据您的代码,即使只满足其中一个条件,也会执行doSomething()

  

我也知道,'G'案件将在所有案件中占99%。如果我把它放在列表的顶部,我可以假设它将作为第一个进行比较吗?

不会检查剩余的案例。

答案 5 :(得分:0)

  

如果满足第一个条件(currentChar ==&#39; G&#39;)如下   案例也进行了评估,或者程序直接跳到doSomething()?

直到它找到break或达到结束为止。

答案 6 :(得分:0)

  

执行速度会更快:switch-case,或带有||的if操作

您应该担心代码的可读性和可支持性,因此请使用更易读的内容。然后,如果您在优化时遇到程序速度问题。

为了便于阅读 - 当然这是主观的,但是通过切换可以减少冗长的代码,因为您不必多次重复变量名称:

if( currentChar == 'G' || currentChar == 'B' || currentChar == 'C' )

所以我希望在这种情况下切换。

答案 7 :(得分:0)

switch (currentChar) {
    case 'G':
    case 'T':                   
    case 'M':
    case ';':                       
    case '\r':                      
    case '\n':  
        doSomething();      
        break;
}

如果doSomething()currentCharGTM;或{{}},则会调用\r {1}}。使用\n比使用普通switch更快,因为if语句通常会优化为跳转表。这就是开关必须以恒定的积分值运行的原因。

答案 8 :(得分:0)

无法保证检查开关盒的顺序。如果表达式没有副作用,也无法保证||的执行顺序 基本上,如果唯一的区别是时间,那么c ++在as-if规则的基础上不保证任何东西的顺序。