首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++拷貝構造函數參數必須是引用:值傳遞導致無限遞歸的底層原理

     編輯:程式設計綜合問答

現象

拷貝構造函數聲明為 `CExample(CExample ex)` (值傳遞) 而非 `CExample(const CExample& ex)` (引用傳遞),創建對象時程序**無限遞歸直到棧溢出**。

逐步推演:為什麼會遞歸?

  1. 調用 `CExample ccc = aaa;` (或傳值調用函數 `func(aaa)`)。
  2. 編譯器需將實參 `aaa` **按值傳遞** 給形參 `ex`。
  3. **按值傳遞意味著調用拷貝構造函數** 創建 `ex` (即 `ex.CExample(aaa)`)。
  4. 進入拷貝構造函數體,**又要按值傳遞 `aaa` 給 `ex`** → **再次調用拷貝構造函數**。
  5. **無限循環**,直到棧內存耗盡拋出 `StackOverflowError` / 段錯誤。

引用傳遞打破循環

`CExample(const CExample& ex)`:

  • 形參 `ex` 是實參 `aaa` 的**別名**,**不創建新對象**,**不調用拷貝構造函數**。
  • 函數體內直接訪問 `ex.m_nTest` 完成拷貝邏輯,遞歸鏈斷開。

代碼對比


// 錯誤:值傳遞 → 無限遞歸
class Bad {
public:
    Bad(Bad other) { } // 形參按值,調用此構造函數需先構造 other → 死循環
};

// 正確:const 引用傳遞 → 無遞歸
class Good {
public:
    Good(const Good& other) { } // 形參是引用,綁定實參,無構造開銷
};

同理:賦值運算符參數也必須是引用


Good& operator=(const Good& other) { // 必須是引用
    if (this != &other) { ... }
    return *this;
}
// 若寫 Good operator=(Good other) 同樣會無限遞歸

總結

**C++ 規定拷貝構造函數、移動構造函數、賦值運算符的參數必須是引用類型** (通常加 `const`)。這不是風格建議,而是**語言機制強制要求**,否則觸發無限遞歸的編譯時/運行時錯誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved