【问题标题】:Case vs If Else If: Which is more efficient? [duplicate]Case vs If Else If:哪个更有效? [复制]
【发布时间】:2010-01-28 23:21:05
【问题描述】:

可能的重复:
is “else if” faster than “switch() case” ?
What is the relative performance of if/else vs. switch in Java?

我再次在运行中进行编码......当调试器单步执行 case 语句时,它会立即跳转到与条件匹配的项目,但是当使用 if/else 指定相同的逻辑时,它会单步执行每个 if 语句,直到找到获胜者。 case 语句更有效,还是我的调试器只是优化了步骤? (不要担心语法/错误,我在 SO 中输入了这个,不知道它是否会编译,这是我所追求的原则,我不想把它们当作整数,因为我隐约记得一些关于使用带整数的偏移量的情况)我使用 C#,但我对跨编程语言的一般答案感兴趣。

switch(myObject.GetType()){

    case typeof(Car):
        //do something
        break;

    case typeof(Bike):
        //do something
        break;

    case typeof(Unicycle):
        //do something
        break;

    case default:
        break;
}

VS

   Type myType = myObject.GetType();

   if (myType == typeof(Car)){
            //do something
   }

   else if (myType == typeof(Bike)){
            //do something
   }

   else if (myType == typeof(Unicycle)){
            //do something
   }
   else{

   }

【问题讨论】:

  • 这甚至不是接近与语言无关的,任何答案都将与一种特定的语言紧密结合。
  • 更不用说具体的编译器和编译器版本了。
  • 它可能因语言、编译器和运行时而异。无法确定。
  • 这甚至不是特定于语言的。它完全取决于特定的编译器实现,即使在那时也可能不是 100% 可回答的(例如,某些形式的 if 语句的优化可能与其他形式不同)。
  • 顺便说一句:这个问题的真正答案是让它们都实现一个通用的接口/抽象方法,例如Vehicle#doSomething() 并且每个都在具体实现中定义本身,所以你最终会得到myObject.doSomething()

标签: performance switch-statement if-statement


【解决方案1】:

似乎编译器在优化 switch 语句方面比 if 语句更好。

编译器不知道评估 if 语句的顺序是否对您很重要,并且无法在那里执行任何优化。您可以在 if 语句中调用方法,从而影响变量。使用 switch 语句,它知道可以同时评估所有子句,并且可以将它们按最有效的顺序排列。

这是一个小比较:
http://www.blackwasp.co.uk/SpeedTestIfElseSwitch.aspx

【讨论】:

  • 我不明白这部分“你可能在 if 语句中调用方法,影响变量” if else 怎么会发生这种情况?我认为是一样的。
  • 你可以这样做 if (++i) { .... },但你不能在 switch case 语句中这样做。
【解决方案2】:

调试器使它变得更简单,因为您不想单步执行编译器创建的实际代码。

如果开关包含五个以上的项目,则使用查找表或哈希表实现,否则使用 if..else 实现。

查看密切相关的问题is “else if” faster than “switch() case” ?

除 C# 之外的其他语言当然会或多或少地以不同的方式实现它,但切换通常更有效。

【讨论】:

    【解决方案3】:

    许多编程语言优化了 switch 语句,使其比标准 if-else if 结构快得多,前提是案例是编译器常量。许多语言使用跳转表或索引branch table 来优化switch 语句。 Wikipedia 对 switch 语句进行了很好的讨论。另外,here 讨论了 C 中的开关优化。

    需要注意的一点是,switch 语句可能会被滥用,根据具体情况,最好使用多态性而不是 switch 语句。示例见here

    【讨论】:

      【解决方案4】:

      我相信因为 case 必须是常量值,switch 语句相当于 goto,所以根据变量的值跳转到正确的 case,而在 if/then 语句中它必须评估每个表达式。

      【讨论】:

        【解决方案5】:

        它可以对 case 语句执行此操作,因为值是编译器常量。更详细的解释在这里http://sequence-points.blogspot.com/2007/10/why-is-switch-statement-faster-than-if.html

        【讨论】:

          【解决方案6】:

          我认为这只是调试器使它变得简单。 请注意,案例和“如果列表”最终并不相同。案例块通常以“break”结尾是有原因的。 case stmt 在汇编中分解时实际上看起来像这样。

          if myObject.GetType() == type of Car
              GOTO START_CAR
          else if myObject.GetType() == type of Bike
              GOTO START_BIKE
          
          LABEL START_CAR
          //do something car     
          GOTO END
          
          LABEL START_BIKE
          //do something bike  
          GOTO END
          
          LABEL END
          

          如果您没有休息,那么案例块将缺少“GOTO END” stmts,事实上,如果您降落在“汽车”案例中,您实际上会运行两个部分

          //do something car     
          //do something bike  
          GOTO END
          

          【讨论】:

            【解决方案7】:

            维基百科的Switch statement entry 相当大,实际上相当不错。有趣的点:

            • 开关本身并不快。这取决于语言、编译器和特定用途。
            • 编译器可能使用跳转表或索引函数指针优化开关。
            • 该声明的灵感来自Stephen Kleene(和其他人)的一些有趣的数学。

            有关使用 C 开关的奇怪而有趣的优化,请参阅 Duff's Device

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-06-02
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-03-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多