首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

C++ 善用建構函式與無名物件簡化運算子多載:對稱性與效能雙贏

     編輯:VC 教學

痛點:雙目運算子的對稱性難題

類別 Test 多載 operator+(Test&, int) 可支援 obj + 10,但 **10 + obj 編譯失敗**(找不到 operator+(int, Test&))。若 operator+ 為成員函式,左運算元隱含 this,**無法將 int 放在第一參數**。

傳統解法:額外多載 + inline 轉發


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;
}

核心技巧解析

進階:通用雙目運算子模板 (C++20 概念)


template 
requires requires(T a, U b) { a += b; }
auto operator+(T lhs, U rhs) -> decltype(lhs += rhs, lhs) {
    lhs += rhs;
    return lhs;
}
// 同理可定義 operator-, operator*, ... 只要類型支援對應複合賦值

效能對比

技巧作用
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)。

適用條件與限制

  • 類型需提供 **operator+= (或對應複合賦值)** 且語義正確。
  • 建構函式不應 explicit 阻礙隱式轉換(若需 10 + obj 自動構造)。
  • 適用於**值語義類型**(規則的複製/移動、無多態切片)。
  • 資源管理類型(智慧指標、獨特句柄)需謹慎設計複製/移動語義。

總結

**「以值傳遞左運算元、複用複合賦值、返回副本」** 是現代 C++ 實現雙目算術運算子的最佳模式。它同時解決了對稱性、程式碼重複、效能(NRVO/移動)三大問題,並與標準庫慣例(std::string, std::chrono::duration)一致。下次多載 +, -, * 時,請優先考慮此模式。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案複製/移動次數程式碼重複對稱性
傳統雙重載 + inline 轉發1-2 次複製高手動維護
值傳遞 + += + NRVO0-1 次 (移動/NRVO)低 (單一邏輯)自然支援