當函數必須返回一個新對象時,請直接按值返回,絕不返回 reference 或 pointer 指向局部/靜態/堆對象。
const Rational& operator*(const Rational& lhs, const Rational& rhs) {
Rational result(lhs.n * rhs.n, lhs.d * rhs.d);
return result; // 錯誤!result 生命週期結束,返回懸空引用
}
結果:未定義行為,調用者訪問已銷毀對象。
const Rational& operator*(const Rational& lhs, const Rational& rhs) {
Rational* result = new Rational(lhs.n * rhs.n, lhs.d * rhs.d);
return *result; // 誰負責 delete?極易洩漏
}
結果:資源管理責任模糊,調用者極難正確釋放,異常時必洩漏。
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); // 直接返回對象
}
operator+= 返回 *this)vector::operator[]、map::find->second)共同特徵:**對象生命週期超出函數調用,且所有權不轉移。**
「要返回新對象,就大方地按值返回;編譯器比你聰明,RVO/移動語義早已幫你搞定性能。」