switch在Visual C中如何编译++它的优化程度和速度如何?

发布于 2024-08-27 16:47:49 字数 226 浏览 8 评论 0原文

当我发现我只能在 C++ 的 switch 语句中使用数值时,我认为它和一堆 if-else 之间一定存在一些更深层次的区别。 s。

因此我问自己:

  • 在运行速度、编译时优化和一般编译方面,switchif-elseif-elseif 有何不同?我这里主要说的是MSVC。

As I found out that I can use only numerical values in C++'s switch statements, I thought that there then must be some deeper difference between it and a bunch of if-else's.

Therefore I asked myself:

  • (How) does switch differ from if-elseif-elseif in terms of runtime speed, compile time optimization and general compilation? I'm mainly speaking of MSVC here.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情绪 2024-09-03 16:47:49

开关通常被编译为跳转表(通过比较来找出要运行的代码),或者如果不可能,编译器仍可能对比较重新排序,以便在值之间执行二分搜索(log N比较)。 if-else 链是线性搜索(尽管我认为,如果所有相关值都是编译时积分常量,则编译器原则上可以执行类似的优化)。

A switch is often compiled to a jump-table (one comparison to find out which code to run), or if that is not possible, the compiler may still reorder the comparisons, so as to perform a binary search among the values (log N comparisons). An if-else chain is a linear search (although, I suppose, if all the relevant values are compile-time integral constants, the compiler could in principle perform similar optimizations).

余厌 2024-09-03 16:47:49

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:

此方法更快的原因之一是条件语句内的代码较小(因此,如果条件预测错误,指令缓存损失较小)。此外,“失败”情况的实现变得更加简单(编译器省略了 goto end 语句)。

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

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

Switch statements are often a common source of compiler optimization. That is, how they are treated depends on the optimization settings you use on your compiler.

The most basic (un-optimized) way of compiling a switch statement is to treat it as a chain of if ... else if ... statements. The common way that compilers optimize a switch is to convert it to a jump table which can look something like:

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:

One reason this method is faster is because the code inside the conditionals is smaller (so there's a smaller instruction cache penalty if the conditional is mis-predicted). Also, the "fall-through" case becomes more trivial to implement (the compiler leaves off the goto end statement).

Compilers can further optimize the jump table by creating an array of pointers (to the locations marked by the labels) and use the value you are switching on as an index into that array. This would eliminate nearly all of the conditionals from the code (except for whatever was needed to validate whether the value you are switching on matches one of your cases or not).

A word of caution: nested jump tables are difficult to generate and some compilers refuse to even try to create one. For that reason, avoid nesting a switch inside another switch if maximally-optimized code is important to you (I'm not 100% sure how MSVC in particular handles nested switches, but the compiler manual should tell you).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文