在Switch case中默认

时间:2012-12-28 07:24:57

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

以下是我需要优化和计划的代码,以便切换到最佳状态。但我可以比较一下。所以我计划将comaparision(len> 3)作为默认情况。

如果我将比较部分(len> 3)作为默认情况并在swith中添加默认值,它会更快吗?

或者如何将以下代码作为switch语句?

            if ( len > 3 ) {
                    which will happen more often;
            }               
            else if ( len == 3 ) {
                    next case which may occur often;
            } else if ( len == 2 ) {        
                   the next priority case;
            } else {
                    and this case occurs rarely;
            }

6 个答案:

答案 0 :(得分:6)

可能不是。 if...elseswitch...case都是高级构造。什么减慢你的速度是分支预测。预测越好,代码运行得越快。您应该将最常见的案例放在if中,将else if放在第二位,依此类推,就像您写的那样。对于switch,结果取决于内部编译器实现,它可以对您的订单进行重新排序。实际应该为较少发生的情况保留default,因为必须先检查其余条件,然后再回到default

总而言之,只要您按正确的顺序设置条件,if...else在性能方面的使用就是最佳的。关于switch...case它的特定编译器,取决于应用的优化。

另请注意,switch...caseif...else更受限制,因为它仅支持简单的值比较。

答案 1 :(得分:3)

虽然你已经接受了可能是最好的答案,但我想提供另一种选择。

请注意,标准警告适用 - 优化不是优化,除非您已经分析了代码。

但是,如果您遇到与分支相关的不良表现,您可以减少或消除它们。你的代码有一个或多个不等式比较并不是一个障碍 - 你可以将你的案例减少到一组直接的等式,如果有必要,用它来索引一个表,而不是分支。

void doSomething(int len)
{
    static const char* str[] =
    {   "%2d > 3\n",
        "%2d < 2\n",
        "%2d = 2\n",
        "%2d = 3\n"
    };

    int m1 = (len-2)>>31;
    int m2 = (len-4)>>31;

    int r = (len & m2 & ~m1) + !!m1;

    printf(str[r],len); 
}

请注意,这些代码做了一些假设,这些假设在实践中可能无法实现,但是我们正在做出这样的假设,即首先需要优化......

另外,请注意,通过更多地了解输入参数的实际范围和类型,以及实际采取的操作需要,可以实现更好的优化。

答案 2 :(得分:2)

你无法将比较移动到switch语句中..它使用单一检查进行选择..即:

switch (len) {

    case 1:
        // do case 1 stuff here
    break;
    case 2:
        // do case 2 stuff here
    break;
    case 3:
        // do case 3 stuff here
    break;
}

使用中断来防止案例陈述相互碰撞了解更多here

您的代码是“优化的”,因为它将处于当前状态..

答案 3 :(得分:1)

如果您担心速度问题,事实是您的if...elseswitch...case语句不会对您的申请速度产生实际影响,除非您有数百个。丢失速度的地方在迭代或循环中。要专门回答您的问题,您无法将if...else语句转换为switch...case语句,而default首先出现;但话虽如此,如果你确实转换为switch...case,那么你将会以相同的速度运行(差异太小,无法通过传统的基准测试工具获取)。

答案 4 :(得分:1)

你要知道的唯一方法就是用它来衡量它 编译器。如果性能有问题,您应该使用该选项 为编译器提供探查器输出,让它决定; 它通常会找到最佳解决方案。 (注意即使在 像英特尔这样的特定架构,就其而言是最佳解决方案 机器指令可能因处理器而异 接下来。)

在您的情况下,开关可能看起来像:

switch ( len ) {
case 2:
    //  ...
    break;

case 3:
    //  ...
    break;

default:
    if ( len > 3 ) {
        // ...
    } else {
        // ...
    }
}

只有两个有效的情况,编译器没有多少 与...合作。一个典型的实现(没有极端 优化)将进行边界检查,然后进行表查找 两个明确的案例。然后任何体面的编译器都会接受 您default案例中的比较对应于其中一项 它已经完成的边界检查,而不是重复它。 但只有两种情况,跳转表可能不会 与两次比较相比有显着差异, 尤其是在最常见的情况下,你将会出类拔萃。

直到你有实际的探查器信息 代码中的瓶颈,我不担心。一旦您 有了这些信息,您可以查看不同的变体 哪个更快,但我怀疑如果你使用最大值 优化和Feed分析信息重新进入 编译器,没有区别。

答案 5 :(得分:0)

您可以在案例中使用范围:

switch (len) {
  case 3 ... INT_MAX:
    // ...
    break;
  case 2:
    // ...
    break;
  default:
    // ...
    break;
 }

编辑:但这是GCC提供的扩展......