C++ 效能優化不僅關乎演算法,更關乎對語言機制的深度理解。本文透過一個簡單的 intPair 結構與三個 Sum 函數的對比實驗,揭示臨時物件建構、複製建構、隱式轉換對效能的實際影響,並分析編譯器優化行為。
struct intPair {
int ip1, ip2;
intPair(int i1, int i2) : ip1(i1), ip2(i2) {}
intPair(int i1) : ip1(i1), ip2(i1) {} // 單參數建構子 → 隱式轉換來源
};
// 1. 值傳遞 (by value)
int Sum1(intPair p) { return p.ip1 + p.ip2; }
// 2. 參考傳遞 (by reference)
int Sum2(intPair &p) { return p.ip1 + p.ip2; }
// 3. 常數參考傳遞 (by const reference)
int Sum3(const intPair &p) { return p.ip1 + p.ip2; }
double Sum(int testCase, int loop) {
clock_t begin = clock();
int x = 0;
switch (testCase) {
case 1: // 每次建構臨時物件傳給 Sum1 (值傳遞)
for (int i=0; i<loop; ++i) x += Sum1(intPair(1,2));
break;
case 2: // 重複使用同一物件傳給 Sum1 (值傳遞)
intPair p1(1,2);
for (int i=0; i<loop; ++i) x += Sum1(p1);
break;
case 3: // 重複使用同一物件傳給 Sum2 (參考傳遞)
intPair p2(1,2);
for (int i=0; i<loop; ++i) x += Sum2(p2);
break;
case 4: // 重複使用同一物件傳給 Sum3 (常數參考傳遞)
intPair p3(1,2);
for (int i=0; i<loop; ++i) x += Sum3(p3);
break;
case 5: // 整數隱式轉換為 intPair 傳給 Sum3
for (int i=0; i<loop; ++i) x += Sum3(10); // int → intPair(10,10)
break;
}
clock_t end = clock();
return double(end - begin) / CLOCKS_PER_SEC;
}
| 情境 | 描述 | 耗時 | 相對效能 |
|---|---|---|---|
| 1 | 每次建構臨時物件 + 值傳遞 | 18 ms | 最慢 (基準 1.0x) |
| 2 | 重複物件 + 值傳遞 (複製建構) | 9 ms | 快 2x |
| 3 | 重複物件 + 參考傳遞 | 6 ms | 快 3x |
| 4 | 重複物件 + 常數參考傳遞 | 7 ms | 快 2.6x |
| 5 | 整數隱式轉換 + 常數參考 | 12 ms | 中等 |
intPair(1,2) 建構臨時物件explicit 防隱式轉換p1 建構一次,但每次呼叫 Sum1(p1) 仍需複製建構Sum2 (非 const 參考) 與 Sum3 (const 參考) 生成機器碼幾乎相同const 僅影響編譯期檢查,不影響執行期代碼生成Sum3(10) 觸發 intPair(int) 單參數建構子,隱式建立 intPair(10,10) 臨時物件explicit 關鍵字,除非確定需要隱式轉換const T&,除非需要修改引數或類型極小 (int, pointer)explicit-O2/-O3 啟用優化,並檢視組合語言輸出驗證效能優化的核心在於「可見化隱藏成本」。理解建構子、複製、轉換、參考的機制,才能寫出既符合直覺又高效率的 C++ 代碼。下一篇將探討記憶體佈局、快取友善設計與演算法層面優化。