類別 Test 多載 operator+(Test&, int) 可支援 obj + 10,但 **10 + obj 編譯失敗**(找不到 operator+(int, Test&))。若 operator+ 為成員函式,左運算元隱含 this,**無法將 int 放在第一參數**。
class Test {
int a;
public:
Test(int v): a(v) {}
friend Test operator+(Test&, int); // obj + 10
friend inline Test operator+(int, Test&); // 10 + obj
int get() const { return a; }
};
Test operator+(Test& lhs, int rhs) { return Test(lhs.get() + rhs); }
inline Test operator+(int lhs, Test& rhs) { return rhs + lhs; } // 轉發
缺點:程式碼重複、維護兩個函式、成員函式版無法解決對稱性。
class Test {
int a;
public:
explicit Test(int v=0): a(v) {} // explicit 防隱式轉換驚喜
int get() const { return a; }
// 成員複合賦值
Test& operator+=(int rhs) { a += rhs; return *this; }
};
// 非成員非友元,利用建構函式 + += 實現雙目 +
Test operator+(Test lhs, int rhs) { // lhs 以**值傳遞**接收左運算元(或無名物件)
lhs += rhs; // 修改副本
return lhs; // 返回副本(NRVO/移動優化)
}
Test operator+(int lhs, Test rhs) { // 對稱版
rhs += lhs;
return rhs;
}
| 技巧 | 作用 | ||
|---|---|---|---|
Test operator+(Test lhs, int rhs) 以值傳遞左運算元 | 呼叫端 obj + 10 → 複製構造 lhs (或移動);10 + obj → 隱式構造 Test(10) 作為 lhs,obj 複製構造 rhs。統一邏輯! | ||
利用 operator+= 修改副本 | 複用修改邏輯,確保 + 與 += 語義一致。 | ||
| 返回值優化 (NRVO/RVO) + 移動語義 (C++11) | 返回區域物件 lhs **零拷貝**,直接構造於呼叫端儲存位置。 | ||
無名物件 Test(10) 隱式轉換 | 10 + obj 先構造臨時 Test(10),再呼叫 operator+(Test, Test)(若有)或上述 operator+(int, Test)。 |
| 方案 | 複製/移動次數 | 程式碼重複 | 對稱性 |
|---|---|---|---|
| 傳統雙重載 + inline 轉發 | 1-2 次複製 | 高 | 手動維護 |
| 值傳遞 + += + NRVO | 0-1 次 (移動/NRVO) | 低 (單一邏輯) | 自然支援 |