Item 21 需要返回物件時,不要返回引用

2022-05-28 04:39:08 字數 1173 閱讀 7054

乙個典型的場景如下:

class rational;

friend const rational operator*(const rational& lhs, const rational& rhs);

rational a, b;

rational c = a*b;

注意operator*返回的是 rational 例項,a*b時便會呼叫operator*(), 返回值被拷貝後用來初始化 c。這個過程涉及到多個構造和析構過程:

我們能否通過傳遞引用的方式來避免這些函式呼叫?這要求在函式中建立那個要被返回給呼叫者的物件,而函式只有兩種辦法來建立物件:在棧中建立、或者在堆中建立。在棧中建立顯然是錯誤的:

const rational& operator*(const rational& lhs, const rational& rhs)
這個函式返回乙個引向 result 的引用,但是 result 是乙個區域性物件,而區域性物件在函式退出時被銷毀。這樣的呼叫將會產生未定義的行為。

如果在堆上建立:

const rational& operator*(const rational& lhs, const rational& rhs)
既然是 new 的物件,那麼誰來 delete 呢?比如下面的客戶**:

rational w, x, y, z;

w = x*y*z;

上面這樣合理的**都會導致記憶體洩露,那麼operator*的實現顯然不夠合理。此時你可能想到用靜態變數來儲存返回值,也可以避免返回值被再次構造。但靜態變數首先便面臨著執行緒安全問題,除此之外當客戶需要不止乙個的返回值同時存在時也會產生問題:

if((a*b) == (c*d))
如果operator*的返回值是靜態變數,那麼上述條件判斷恆成立,因為等號兩邊是同乙個物件嘛。

掙扎了這許多,我們還是返回乙個物件吧:

inline const rational operator*(const rational& lhs, const rational& rhs)

Item 28 不要返回物件內部的控制代碼

控制代碼 handle 可以理解為持有其它物件的方法,引用,指標,和迭代器都是控制代碼。不要返回物件私有成員的控制代碼。這樣可以增加類的封裝性 使得 const 函式更加 const,也避免了空引用的建立。直接返回私有成員的指標會導致私有成員被完全暴露。例如 class point struct r...

條款21 必須返回物件時,別妄想返回其引用

條款21 必須返回物件時,別妄想返回其引用 includeusing namespace std class rational private int n,d friend const rational operator const rational lhs,const rational rhs c...

在必須返回乙個物件時,不要去嘗試返回乙個引用

一旦程式設計師把注意力都轉向了物件傳值方式隱含的效率問題 參見第 20 條 時,許多人都變成了極端的 改革運動者 他們對傳值方法採取斬草除根的態度,在他們不屈不撓追求傳遞引用方式的純粹性的同時,他們也犯下了致命的錯誤 有時候傳遞的引用所指向的物件並不存在。這決不是一件好事情。請看下面的示例,其中的 ...