C++ switch 语句评估

C++ switch statement evaluation

假设我们有以下代码:

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

如果满足第一个条件(currentChar == 'G')是否还要比较下面的情况,或者程序直接跳转到doSomething()?

什么执行起来更快:switch-case,还是带有 || 运算符的 if?

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

If the first condition is met (currentChar == 'G') are the following cases also evaluated, or the program jumps straight to doSomething()?

会立即跳转执行doSomething()

What would be faster to execute: the switch-case, or an if with || operator?

我认为它对任何像样的现代 c++ 编译器没有任何影响,发出的代码应该完全相同。

What would be faster to execute: the switch-case, or an if with || operator?

争取 switch()。如果您有一个设置了小值的枚举或整数,switch() 通常会创建一个跳转 table。

If the first condition is met (currentChar == 'G') are the following cases also evaluated, or the program jumps straight to 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 语句的最后一条语句。请参阅 this link 以获取 switch 语句的工作示例。

What would be faster to execute: the switch-case, or an if with || operator?

假设您使用的是一个不错的编译器,差异很小,可以忽略不计。请参阅 this 所以 link,以防您需要了解更多细节。

编辑以供澄清

I want doSomething() to be executed if any of the conditions is met.

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

I also know that the 'G' case will occur in some 99% of all cases. Can I assume that it will be compared as the first if I put it on top of the list?

其余情况将不检查。

If the first condition is met (currentChar == 'G') are the following cases also evaluated, or the program jumps straight to doSomething()?

它一直掉下去,直到找到 break 或到达终点。

一旦 currentChar'G' 进行比较,指令跳转到指令 doSomething()。您不能依赖案例的顺序 "optimize" switch.

请注意,比较不需要按顺序进行。
switch 可以实现为跳转 table 例如:

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

What would be faster to execute: the switch-case, or an if with || operator?

您应该担心代码的可读性和可支持性,因此请使用对您而言更具可读性的内容。然后,如果您对程序速度有疑问,请进行优化。

为了可读性——当然这是主观的,但是使用 switch 可以减少冗长的代码,因为您不必多次重复变量名:

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

所以我更愿意在这种情况下切换。

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

这使得 doSomething()currentCharGTM;\r 时被调用或 \n。使用 switch 比使用普通的 if 更快,因为 switch 语句通常被优化为跳转表。这就是为什么开关必须在恒定的整数值上运行。

无法保证 switch case 中的检查顺序。如果表达式没有副作用,也无法保证 || 的执行顺序。
基本上,如果唯一的区别是时间,C++ 不保证任何东西的顺序,基于 as-if 规则。

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

以下是 gcc5.3 在优化通过后如何处理这段代码:

test(char):
        cmpb    , %dil
        je      .L3      
        jle     .L6       
        cmpb    , %dil
        je      .L3
        cmpb    , %dil
        je      .L3
        cmpb    , %dil
        je      .L3
.L1:
        rep ret
.L6:
        cmpb    , %dil
        je      .L3
        cmpb    , %dil
        jne     .L1
.L3:
        jmp     doSomething()

我真的不认为如果不创建 256 条目跳转 table,你可以写得更快,这将在缓存位置和耗尽方面产生自己的后果。