优秀的编译器可以并且会在跳转表、链接式if/else和二者的组合中进行选择。而设计不良的编译器可能不会做出这样的选择,甚至对于 switch-blocks 生成非常糟糕的代码。但是任何像样的编译器都应该能够为 switch-blocks 生成高效的代码。
这里的主要决策因素是:当数字相差很远时(而不是通过除以2、4、8、16、256等将其轻易地更改为较接近的值),编译器可以选择 if/else,例如:
switch(x)
{
case 1:
...
case 4912:
...
case 11211:
...
case 19102:
...
}
如果需要跳转表,至少需要19102 * 2字节的空间。
另一方面,如果数字接近,编译器通常会使用跳转表。
即使是 if/else
类型的设计,它通常也会执行“二分查找” - 如果我们采用上面的例子:
if (x <= 4912)
{
if (x == 1)
{
....
}
else if (x == 4912)
{
....
}
} else {
if (x == 11211)
{
....
}
else if (x == 19102)
{
...
}
}
如果我们有很多案例,这种方法会嵌套得很深,人们可能在三到四个层级的深度之后就会迷失方向(请记住,每个 if 语句都从范围的中间某一点开始),但它可以将测试的数量减少 log2(n) 次,其中 n 是选择的数量。它比朴素的方法要更有效率。
if (x == first value) ...
else if (x == second value) ...
else if (x == third value) ...
..
else if (x == nth value) ...
else ...
如果能在if-else语句的开头放置某些值,这样做会稍微好一些,但前提是在运行代码之前就能确定最常见的值。
如果性能对你的情况至关重要,那么你需要对两种方案进行基准测试。但我猜只需将代码编写为switch语句,不仅代码更清晰,而且至少与if-else语句一样快,甚至更快。