for迴圈中 i和i 的效率問題

2021-10-08 23:53:59 字數 1528 閱讀 8774

不知道你是否聽說過++i比i++快的說法,真的如此嗎?

這兩個表示式從我們初學程式語言的時候就會接觸到。前者是自增後取值,後者是取值後自增

我們看乙個簡單的例子。

#include

using

namespace std;

intmain()

執行結果:

c=

0;d=

1

對於這個結果我們並不感到意外。

另外我們還注意到另外乙個有意思的現象:

#include

using

namespace std;

intmain()

編譯後報錯:

main.cpp:7:

19: error: lvalue required as unary 『&』 operand

int*c =

&(a++

);

說&作用於左值,也就是說a++的結果並非左值。但++b的結果是左值。

可簡單理解左值和右值:

在《運算子過載》一文中已經說到了運算子的過載,通過前面的例子也發現了,對於內建型別,前置自增返回物件的引用,而後置自增返回物件的原值(但非左值)。

基於上述原則,乙個前置版本和後置版本的常見實現如下:

class

test

;/*前置自增實現正規化*/

test& test::

operator++(

)/*後置自增實現正規化,為了與前置區分開,多了乙個int引數,但從來沒用過*/

const test test::

operator++(

int)

仔細觀察後,我們發現前置自增,先自增,後返回原物件的物件;沒有產生任何臨時物件;而後置自增,先儲存原物件,然後自增,最後返回該原臨時物件,那麼它就需要建立和銷毀,這樣一來,效率孰高孰低就很清楚了。

在不進行賦值的情況下,內建型別前置和後置自增的彙編都是一樣的呢!

void

test()

彙編:

push    rbp

mov rbp, rsp

mov dword ptr [rbp-4]

,0add dword ptr [rbp-4]

,1noppop rbp

ret

不過,賦值的情況下,並且不開啟編譯器優化,它們的彙編**還是有差別的,有興趣的可以試試。

對於內建型別,前置和後置自增或者自減在編譯器優化的情況下,兩者並無多大差別,而對於自定義型別,如無特別需要,人們似乎更加偏愛前置自增或自減,因為後置自增常常會產生臨時物件。

但是,又能提高多少效率呢?

推薦閱讀:

什麼是運算子的過載?

for迴圈中 i和i 的區別

語法 for 語句1 語句2 語句3 語句 1 在迴圈 塊 開始前執行 語句 2 定義執行迴圈 塊 的條件 語句 3 在迴圈 塊 已被執行之後執行 這就是迴圈中的 i和i 結果一樣的原因,但是效能不一樣,稍後解釋 語句1 同上面語法中的 語句1 語句1 是可選的,也就是說不使用語句1 也可以。var...

for迴圈中 i和i 的區別

for 語句1 語句2 語句3 語句 1 在迴圈 塊 開始前執行 語句 2 定義執行迴圈 塊 的條件 語句 3 在迴圈 塊 已被執行之後執行 前者是 先引用,後增加,int i 10 system.out.println i 此時輸出的是10以上 等價與 int i 10 system.out.pr...

for迴圈中的i 與 i

今天遇到乙個for迴圈 for i 1 i 1 i 其中使用的是 i,我以為 i會先於判斷執行,就上網找了找i 與 i的區別。答案很少,有乙個說的是效率後者高一些。然後我又寫了乙個測試的 var j 0 for i 1 i 1 i,j console.log console.log i,j 發現 是...