C++ 允許單引數建構子隱式轉換,方便但有代價。當類別定義 UPInt(int) 並提供 operator+(UPInt, UPInt) 時,upi + 10 會建立暫時 UPInt(10) 再呼叫運算子。本文展示以多載取代隱式轉換,消除暫時物件開銷的技巧與陷阱。
class UPInt {
public:
UPInt(); UPInt(int value); // 隱式轉換來源
};
const UPInt operator+(const UPInt&, const UPInt&);
UPInt upi1, upi2, upi3;
upi3 = upi1 + upi2; // 直接呼叫 operator+(UPInt, UPInt)
upi3 = upi1 + 10; // 隱式建立 UPInt(10) → 暫時物件
upi3 = 10 + upi2; // 隱式建立 UPInt(10) → 暫時物件
// 原版
const UPInt operator+(const UPInt& lhs, const UPInt& rhs);
// 新增:UPInt + int
const UPInt operator+(const UPInt& lhs, int rhs) {
return UPInt(lhs.Value() + rhs); // 直接運算,無暫時物件
}
// 新增:int + UPInt
const UPInt operator+(int lhs, const UPInt& rhs) {
return UPInt(lhs + rhs.Value());
}
// 現在無暫時物件
upi3 = upi1 + 10; // 呼叫 operator+(UPInt, int)
upi3 = 10 + upi2; // 呼叫 operator+(int, UPInt)
const UPInt operator+(int lhs, int rhs); // 錯誤!編譯失敗
C++ 規則:多載運算子至少需一個使用者定義型別參數。int + int 屬於內建行為,不可多載,否則將破壞語言核心語意。
| 類別 | 隱式轉換來源 | 多載策略 |
|---|---|---|
| 字串類別 | const char* | 提供 operator+(String, const char*) 等 |
| 數值類別 | int, double | 提供混合運算多載 |
| 智慧指標 | 原始指標 T* | 提供建構子 explicit、比較運算子 |
「只有在確信整體效能顯著提升時,才實作大量多載。否則維護成本超過收益。」—— Effective C++ 條款 16
explicit 建構子防止非預期隱式轉換explicit 建構子 + operator T() 轉換函數雙向控制std::string_view 避免 const char* → std::string 暫時物件多載消除隱式轉換是經典 C++ 效能優化技巧,核心在於「提供編譯器最佳匹配,避免暫時物件」。配合 explicit、移動語意、string_view 等現代特性,能在保持介面直覺的同時達到極致效能。