C 中for和foreach迴圈的效能

2021-05-26 22:01:38 字數 1145 閱讀 9650

大家先來看看如下三個迴圈:

int foo = new int[100];

1,foreach (int i in foo)

console.writeline(i.tostring());

複製**

2,for(int index=0;index

console.writeline(foo[index].tostring());

複製**

3,int len=foo.length;

for(int index=0;index

console.writeline(foo[index].tostring());

複製**

這三個迴圈是我在看《

》中看到的,發現書中說第三個迴圈和如下**等效,經過使用ildasm.exe

工具檢視il**發現這個說法並不正確:

int len=foo.length;

for(int index=0;index

複製**

書中的看法是陣列的邊界

測試會被執行兩次(編譯器生成的**一次,jit編譯階段還要執行一次檢查),但是的確沒有在il**中發現c#的編譯器生成類似的邏輯,所以這個說法有問題!

效能上的提公升!經檢視il**,實際情況也就是如此!

但是,這樣寫會帶來另外的問題,那就是破壞了jit對**的進行的

優化,這樣的寫法在每一次迴圈中都要做陣列的邊界檢查,這樣也帶來了效能上的損失,而且這個損失要比每次計算length要大,如果我們按第二種寫法,jit只在第一次迴圈之前檢查一次陣列界限(jit這種優化只針對f迴圈中訪問一維0基數組,並且索引是0和length之間的元素)

看來jit不喜歡我們這樣幫助他優化**,這樣反而破壞了jit本身的優化!

我們再來看看第一種寫法和第二種寫法,通過檢視il**,他們生成的**比較類似,差別是使用foreach迴圈是把陣列元素放到i變數裡!

c#編譯器對第一種寫法(使用foreach迴圈)針對陣列做了特殊的處理,並沒有像其他集合那樣在內部使用迭代器,這裡如果使用迭代器的話會導致裝箱和拆箱操作,這樣會帶來效能上的損失!看來c#編譯器總是可以為foreach生成很高效率的**,而且可以帶來很多其他的好處,例如簡化**的編寫,或是將來把foo變成其他集合 而foreach迴圈不必修改(使用for迴圈必須修改**),運算元強制型別轉換等。

for迴圈和foreach迴圈的比較

1.在固定長度或者長度不需要計算的時候for迴圈效率高於foreach,foreach在迴圈次數未知或者計算起來較複雜有損效能的情況下效率比for迴圈高。2.foreach適用於只是進行集合或陣列遍歷,for則在較複雜的迴圈中效率更高。什麼是複雜環境呢?就是要對原陣列進行修改時。3.foreach與...

JAVA中的for each迴圈

for each是jdk5.0新增加的乙個迴圈結構,可以用來以此處理陣列中的每個元素 其他型別的元素集合也可以 而不用為指定下標而分心。格式如下 for variable collection statement 定義乙個變數用於暫存集合中的每乙個元素,並執行相應的語句 當然,也可以是語句塊 集合表...

PHP中的foreach迴圈

php中的foreach語句,常用於遍歷陣列。foreach一般有兩種使用方式 1 只取陣列的值,不取陣列的下標 2 取陣列值,同時也取陣列的下標 以下面的例1和例2來解釋其用法 例1 只取值,不取下標 member array 201201 tom 201203 jack 201211 james...