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++ 的典型標誌。