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

Effective C++ 條款 21:必須返回對象時,絕不返回 reference — 完整論證

     編輯:C++ 入門

核心法則

當函數必須返回一個新對象時,請直接按值返回,絕不返回 reference 或 pointer 指向局部/靜態/堆對象。

三種錯誤嘗試及其致命缺陷

1. 返回局部對象的 reference

const Rational& operator*(const Rational& lhs, const Rational& rhs) {
    Rational result(lhs.n * rhs.n, lhs.d * rhs.d);
    return result;  // 錯誤!result 生命週期結束,返回懸空引用
}

結果:未定義行為,調用者訪問已銷毀對象。

2. 返回 heap 對象的 reference

const Rational& operator*(const Rational& lhs, const Rational& rhs) {
    Rational* result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);
    return *result;  // 誰負責 delete?極易洩漏
}

結果:資源管理責任模糊,調用者極難正確釋放,異常時必洩漏。

3. 返回 static 對象的 reference

const Rational& operator*(const Rational& lhs, const Rational& rhs) {
    static Rational result;
    result = Rational(lhs.n * rhs.n, lhs.d * rhs.d);
    return result;  // 線程不安全、連續調用覆蓋、多對象需求無法滿足
}

結果:多線程競態、a*b == c*d 永遠為 true、無法支持 (a*b) == (c*d) 等表達式。

正確做法:按值返回

inline Rational operator*(const Rational& lhs, const Rational& rhs) {
    return Rational(lhs.n * rhs.n, lhs.d * rhs.d);  // 直接返回對象
}

編譯器優化保證

  • 返回值優化 (RVO/NRVO):編譯器直接在調用者棧幀構造對象,零拷貝
  • 移動語義 (C++11):即使無法 RVO,移動構造函數極廉價(指針轉移)
  • 現代編譯器(GCC/Clang/MSVC)對簡單返回值優化極其激進,性能無損

何時可以返回 reference?

  • 返回參數引用(如 operator+= 返回 *this)
  • 返回類靜態常量/單例
  • 返回容器元素(vector::operator[]、map::find->second)
  • 返回全局/命名空間作用域對象

共同特徵:**對象生命週期超出函數調用,且所有權不轉移。**

總結口訣

「要返回新對象,就大方地按值返回;編譯器比你聰明,RVO/移動語義早已幫你搞定性能。」

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