回答

35

一個開關通常被編譯爲一個跳轉表(比較一個以找出要運行的代碼),或者如果這是不可能的,編譯器仍然可以對比較進行重新排序,以執行二分查找值之間(log N比較)。一個if-else鏈是一個線性搜索(儘管我猜想,如果所有相關的值都是編譯時積分常量,編譯器原則上可以執行類似的優化)。

+0

+1爲好的答案。我也將利用這個機會貶低if-then-elseif鏈。不止一個「其他」如果是DDD(設計缺陷障礙)的標誌。 – 2010-07-19 15:15:46

+5

這是VisualC++的[真實世界C++開關實現](http://www.codeproject.com/Articles/100473/Something-You-May-Not-Know-About-the-Switch-Statem)。 – 2014-06-24 09:42:57

+0

現在,如果這是優化,如果他們可以,這將是很好的。 – Lothar 2015-11-15 21:11:31

8

開關語句通常是編譯器優化的常見來源。也就是說,它們的處理方式取決於您在編譯器上使用的優化設置。

編譯switch語句的最基本的(未優化的)方式是將其視爲一個if ... else if ...語句的鏈。該編譯器優化開關的常用方法是將其轉換爲一個jump table可以看起來像:

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: 

一個原因這個方法更快是因爲條件語句中的代碼是小(所以有一個小的指令緩存如果條件被錯誤預測則罰款)。另外,「fall-through」情況變得更加微不足道(編譯器留下goto end聲明)。

編譯器可以通過創建一個指針數組(通過標籤標記的位置)來進一步優化跳轉表,並使用您打開的值作爲該數組的索引。這將消除代碼中的幾乎所有條件(除了驗證您所接入的值是否與您的某個案例相匹配所需的內容)。

請注意:嵌套跳轉表很難生成,有些編譯器甚至拒絕創建一個。因此,如果最大限度優化的代碼對您很重要(我不是100%確定MSVC如何處理嵌套的switch es,但編譯器手冊應告訴您),請避免在另一個switch中嵌套switch

+0

注意:我沒有提及任何有關交換機性能的相關if-else樹的具體數字,因爲優化的好處嚴重依賴於代碼。告訴你從優化中獲得多少改進的唯一真正方法是以兩種方式編寫代碼並測量運行每個代碼需要多長時間。 – bta 2010-07-19 19:46:34

+13

給定的代碼是***不是跳轉表。這件事根本不代表任何表格。然而,維基百科的鏈接確實提供了正確的例子。 – dualed 2013-02-20 11:01:36

相關問題