使用
语句与使用
30的语句
枚举,其中大约10个具有预期的操作(目前是相同的操作)。性能和空间需要考虑,但不是关键因素。我已经对代码片段进行了抽象,所以请不要因为命名约定而讨厌我。
声明:
// 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;
}
声明:
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();
}
发布于 2008-09-18 23:32:47
使用开关。
在最坏的情况下,编译器将生成与if-else链相同的代码,因此您不会丢失任何内容。如果有疑问,请将最常见的情况放在switch语句中。
在最好的情况下,优化器可能会找到一种更好的方法来生成代码。编译器通常做的事情是构建一个二进制决策树(在平均情况下保存比较和跳转),或者简单地构建一个跳转表(工作时根本不需要比较)。
发布于 2008-09-24 20:01:20
对于您在示例中提供的特殊情况,最清晰的代码可能是:
if (RequiresSpecialEvent(numError))
fire_special_event();
显然,这只是将问题转移到代码的不同区域,但现在您有机会重用此测试。对于如何解决它,您也有更多的选择。您可以使用std::set,例如:
bool RequiresSpecialEvent(int numError)
{
return specialSet.find(numError) != specialSet.end();
}
我并不是说这是RequiresSpecialEvent的最佳实现,只是说它是一种选择。您仍然可以使用switch或if-else链,或者查找表,或者对值进行一些位操作。你的决策过程变得越模糊,你从一个孤立的函数中获得的价值就越大。
发布于 2008-09-19 16:12:56
交换机
是
快点。
只需尝试if/else-ing一个循环中的30个不同的值,并使用switch将其与相同的代码进行比较,看看switch的速度有多快。
现在,
交换机有一个真正的问题
:开关必须在编译时知道每个case中的值。这意味着以下代码:
// 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 ;
}
}
不会编译。
然后,大多数人将使用定义(啊!),其他人将在同一编译单元中声明和定义常量变量。例如:
// 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/
https://stackoverflow.com/questions/97987
复制相似问题