如何在Visual C++中编译切换以及如何优化和快速?

eku*_*kul 29 c++ if-statement switch-statement visual-c++ visual-c++-2010

当我发现我只能在C++的switch语句中使用数值时,我认为那里必须有一些更深的区别if-else.

所以我问自己:

  • (如何)在运行时速度,编译时优化和常规编译方面switch有所不同if-elseif-elseif?我这里主要谈的是MSVC.

Unc*_*ens 37

通常将开关编译为跳转表(一个比较以找出要运行的代码),或者如果不可能,则编译器仍然可以对比较进行重新排序,以便在值之间执行二进制搜索(log N比较).if-else链是一个线性搜索(虽然,我想,如果所有相关值都是编译时积分常数,编译器原则上可以执行类似的优化).

  • 这是VisualC++的[真实世界C++开关实现](http://www.codeproject.com/Articles/100473/Something-You-May-Not-Know-About-the-Switch-Statem). (5认同)

bta*_*bta 7

Switch语句通常是编译器优化的常见来源.也就是说,它们的处理方式取决于您在编译器上使用的优化设置.

编译switch语句的最基本(未优化)方法是将其视为if ... else if ...语句链.编译器优化开关的常用方法是将其转换为跳转表,其类似于:

if (condition1) goto label1;
if (condition2) goto label2;
if (condition3) goto label3;
else            goto default;
label1:
  <<<code from first `case statement`>>>
  goto end;
label2:
  <<<code from first `case statement`>>>
  goto end;
label3:
  <<<code from first `case statement`>>>
  goto end;
default:
  <<<code from `default` case>>>
  goto end;
end:
Run Code Online (Sandbox Code Playgroud)

这种方法更快的一个原因是因为条件中的代码较小(因此如果条件被错误预测,则会有较小的指令缓存惩罚).此外,"直通"案例变得更加微不足道(编译器不再使用该goto end语句).

编译器可以通过创建指针数组(到标签标记的位置)来进一步优化跳转表,并使用您要切换的值作为该数组的索引.这将消除代码中的几乎所有条件(除了验证您正在接通的值是否与您的一个案例匹配所需的任何条件除外).

需要注意的是:嵌套跳转表很难生成,有些编译器甚至拒绝尝试创建跳转表.因此,如果最大限度优化的代码对您很重要,请避免嵌套switch在另一个内部switch(我不是100%确定MSVC如何处理嵌套switches,但编译器手册应该告诉您).

  • 给定的代码是***而不是跳转表.它根本不代表任何表格.但是,维基百科的链接提供了正确的示例. (16认同)