为了账号安全,请及时绑定邮箱和手机立即绑定

切换if-etc语句的优点

切换if-etc语句的优点

C++
米脂 2019-07-06 15:56:38
切换if-etc语句的优点使用switch语句与使用if发言30unsigned枚举,其中大约10个具有预期的操作(目前是相同的操作)。业绩和空间需要考虑,但并不重要。我已经抽象了片段,所以不要因为命名约定而讨厌我。switch声明:// numError is an error enumeration type, with 0 being the non-error case // fire_special_event() is a stub method for the shared processingswitch (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;       }if声明: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();}
查看完整描述

3 回答

?
互换的青春

TA贡献1797条经验 获得超6个赞

用开关。

在最坏的情况下,编译器将生成与if-etc链相同的代码,因此不会丢失任何东西。如果有疑问,首先将最常见的情况放在Switch语句中。

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


查看完整回答
反对 回复 2019-07-06
?
慕斯王

TA贡献1864条经验 获得超2个赞

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

if (RequiresSpecialEvent(numError))
    fire_special_event();

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

bool RequiresSpecialEvent(int numError){
    return specialSet.find(numError) != specialSet.end();}

我并不是说这是RequiresSpecialEvent的最佳实现,只是说这是一个选项。您仍然可以使用开关或if-Else链,或者查找表,或者对值进行一些位操作,诸如此类。决策过程越模糊,就越能从孤立的函数中获得更多的价值。


查看完整回答
反对 回复 2019-07-06
?
温温酱

TA贡献1752条经验 获得超4个赞

开关更快。

只需尝试循环中的30个不同值,并将其与使用开关的相同代码进行比较,以查看开关的速度有多快。

现在,开关有一个真正的问题:开关必须在编译时知道每种情况下的值。这意味着以下代码:

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

不会编译。

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

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

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

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


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

它当然是的。

外部类型的目的是将值与源分离。将此值定义为宏、作为简单的Constint声明,甚至定义为枚举具有内联值的副作用。因此,如果定义、枚举值或Constint值发生变化,则需要重新编译。Extern声明意味着在发生值更改时不需要重新编译,但另一方面,则不可能使用开关。结论是使用开关将增加交换机代码与用作情况的变量之间的耦合。..当它是好的,然后使用开关。当它不是的时候,那就不足为奇了。


查看完整回答
反对 回复 2019-07-06
  • 3 回答
  • 0 关注
  • 384 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信