首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >switch优于if-else语句的优点

switch优于if-else语句的优点
EN

Stack Overflow用户
提问于 2008-09-18 23:28:24
回答 23查看 123K关注 0票数 178

使用

语句与使用

30的语句

枚举,其中大约10个具有预期的操作(目前是相同的操作)。性能和空间需要考虑,但不是关键因素。我已经对代码片段进行了抽象,所以请不要因为命名约定而讨厌我。

声明:

代码语言:javascript
复制
// numError is an error enumeration type, with 0 being the non-error case
// fire_special_event() is a stub method for the shared processing

switch (numError)
{  
  case ERROR_01 :  // intentional fall-through
  case ERROR_07 :  // intentional fall-through
  case ERROR_0A :  // intentional fall-through
  case ERROR_10 :  // intentional fall-through
  case ERROR_15 :  // intentional fall-through
  case ERROR_16 :  // intentional fall-through
  case ERROR_20 :
  {
     fire_special_event();
  }
  break;

  default:
  {
    // error codes that require no additional action
  }
  break;       
}

声明:

代码语言:javascript
复制
if ((ERROR_01 == numError)  ||
    (ERROR_07 == numError)  ||
    (ERROR_0A == numError)  || 
    (ERROR_10 == numError)  ||
    (ERROR_15 == numError)  ||
    (ERROR_16 == numError)  ||
    (ERROR_20 == numError))
{
  fire_special_event();
}
EN

回答 23

Stack Overflow用户

回答已采纳

发布于 2008-09-18 23:32:47

使用开关。

在最坏的情况下,编译器将生成与if-else链相同的代码,因此您不会丢失任何内容。如果有疑问,请将最常见的情况放在switch语句中。

在最好的情况下,优化器可能会找到一种更好的方法来生成代码。编译器通常做的事情是构建一个二进制决策树(在平均情况下保存比较和跳转),或者简单地构建一个跳转表(工作时根本不需要比较)。

票数 174
EN

Stack Overflow用户

发布于 2008-09-24 20:01:20

对于您在示例中提供的特殊情况,最清晰的代码可能是:

代码语言:javascript
复制
if (RequiresSpecialEvent(numError))
    fire_special_event();

显然,这只是将问题转移到代码的不同区域,但现在您有机会重用此测试。对于如何解决它,您也有更多的选择。您可以使用std::set,例如:

代码语言:javascript
复制
bool RequiresSpecialEvent(int numError)
{
    return specialSet.find(numError) != specialSet.end();
}

我并不是说这是RequiresSpecialEvent的最佳实现,只是说它是一种选择。您仍然可以使用switch或if-else链,或者查找表,或者对值进行一些位操作。你的决策过程变得越模糊,你从一个孤立的函数中获得的价值就越大。

票数 45
EN

Stack Overflow用户

发布于 2008-09-19 16:12:56

交换机

快点。

只需尝试if/else-ing一个循环中的30个不同的值,并使用switch将其与相同的代码进行比较,看看switch的速度有多快。

现在,

交换机有一个真正的问题

:开关必须在编译时知道每个case中的值。这意味着以下代码:

代码语言:javascript
复制
// WON'T COMPILE
extern const int MY_VALUE ;

void doSomething(const int p_iValue)
{
    switch(p_iValue)
    {
       case MY_VALUE : /* do something */ ; break ;
       default : /* do something else */ ; break ;
    }
}

不会编译。

然后,大多数人将使用定义(啊!),其他人将在同一编译单元中声明和定义常量变量。例如:

代码语言:javascript
复制
// WILL COMPILE
const int MY_VALUE = 25 ;

void doSomething(const int p_iValue)
{
    switch(p_iValue)
    {
       case MY_VALUE : /* do something */ ; break ;
       default : /* do something else */ ; break ;
    }
}

因此,最终,开发人员必须在“速度+清晰度”和“代码耦合”之间做出选择。

(并不是说开关不能写成像地狱一样令人困惑……我目前看到的大多数开关都属于这种“令人困惑的”类别……但这是另一回事……)

编辑2008-09-21:

bk1e

添加了以下评论:“

在头文件中将常量定义为枚举是处理此问题的另一种方式。

当然是这样的。

外部类型的要点是将值与源分离。将该值定义为宏、简单的const int声明,甚至是枚举,都会产生内联值的副作用。因此,如果定义、枚举值或常量int值发生更改,则需要重新编译。外部声明意味着在值改变的情况下不需要重新编译,但另一方面,使它不可能使用开关。结论是

使用switch将增加switch代码和用作case的变量之间的耦合。

..。当它是Ok的时候,然后使用开关。那么,当它不是的时候,也就不足为奇了。

..。

编辑2013-01-15:

弗拉德·拉扎连科

评论了我的回答,给出了一个链接,指向他对开关生成的汇编代码的深入研究。非常闪电:

http://lazarenko.me/switch/

票数 25
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/97987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档