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

C++ 返回區域引用:為何用引用接收不崩潰而用值接收崩潰

     編輯:程式設計疑難解答

現象

Teacher& Teacher::retT() {
    Teacher t1(120);
    Teacher& t2 = t1;
    return t2; // 返回區域物件引用 → 未定義行為
}

void main() {
    Teacher t1(12);
    Teacher& t2 = t1.retT(); // 引用接收:看似正常輸出 120
    // Teacher t2 = t1.retT(); // 值接收:崩潰或輸出亂碼
}

根本原因

返回區域物件引用屬於未定義行為 (UB)。函數結束時 t1 生命週期結束,記憶體被回收/覆寫。後續存取皆為「碰運氣」。

為何引用接收「看似正常」

  1. 複製建構子未被呼叫:Teacher& t2 = ... 直接綁定引用,不產生副本,暫時讀取到尚未被覆寫的棧記憶體(殘留值 120)。
  2. 值接收觸發複製建構子:Teacher t2 = ... 呼叫複製建構子 Teacher(const Teacher&),此時來源物件已銷毀,讀取到無效記憶體導致崩潰/亂碼。

正確做法

  1. 返回值 (by value):依賴 RVO/NRVO 編譯器優化,無額外開銷。
    Teacher Teacher::retT() {
        return Teacher(120); // 直接返回臨時物件
    }
  2. 返回靜態/動態分配物件(特殊需求):
    Teacher& Teacher::retT() {
        static Teacher t(120); // 靜態區域變數,生命週期至程式結束
        return t;
    }
    // 或
    Teacher* Teacher::retT() {
        return new Teacher(120); // 呼叫端負責 delete
    }

關鍵觀念

  • 絕不返回區域變數的指標或引用。
  • 現代 C++ (C++11 起) 返回值優化 (RVO) 使 return Teacher(...) 高效且安全。
  • 若類別管理資源 (指標、檔案句柄),務必正确实作 五大特殊函數 (建構子、複製/移動建構子、複製/移動賦值、解構子)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved