C++ 一律寫 ++i,因為後置遞增必須先拷貝一份舊值
對單純的
int,兩者在現代編譯器下效能完全一樣。但 C++ 社群普遍規範一律寫++i——理由不在int,在於這個語法承諾了什麼。
差別在「要不要回傳舊值」
// ++i:直接改值,回傳自己
int& operator++() {
this->value += 1; // 加 1
return *this; // 回傳更新後的自己
}
// i++:必須先暫存舊值
int operator++(int) {
int temp = *this; // 先複製一份舊值
this->value += 1; // 再加 1
return temp; // 回傳剛才那份舊值
}i++ 的語義就是「回傳遞增前的值」,所以它語法本質上包含了「產生暫存副本」的承諾——哪怕在 for 迴圈末尾,你根本不需要那個舊值。
為什麼在 C++ 特別要緊:迭代器是物件
在 JavaScript 裡迴圈跑的只有基本數字型別,所以 i++ 沒差。C++ 的迴圈常常操作 STL 迭代器:
for (auto it = vec.begin(); it != vec.end(); ++it)迭代器是一個 class/struct,不是 4-byte 整數。 寫 it++ 的話,每次迴圈結束都要呼叫拷貝建構子建立暫存物件、再銷毀它——這是真實的記憶體與運算開銷。++it 保證原地修改,零額外負擔。
那 int 呢
現代編譯器(GCC、Clang、MSVC)夠聰明:發現 i++ 的回傳值沒人接收時,會自動最佳化成 ++i,不會真的產生暫存變數。
所以養成 ++i 的習慣,買的不是 int 的那點效能,是兩件別的事:
- 風格一致性:不管計數器是
int、自定義型別、大整數庫還是 STL 迭代器,全部統一寫法,絕對不會踩到效能地雷。 - 慣用法(Idiomatic C++):各大開源專案的
for迴圈都寫++i,這也是判斷一個人熟不熟 C++ 的典型標誌。