讀書筆記 Effective C

2022-03-01 14:17:51 字數 2208 閱讀 6513

當你理解條款21後,很可能出現一種過度使用的情況:只要看到是乙個非內建型別,就去使用引用傳值。舉個書上的例子:

1

class

rational

28 friend const rational& operator* (const rational& r1, const rational&r2)

9 };

numerator表示分子,denominator表示分母,這裡我們需要把注意力放在operator*上,不是在它的形參上(用的const引用是完全正確的),而是在它的返回值上,這個帶引用的返回值是乙個巨大的bug。

我們可以設想一下實現:

1 friend const rational& operator* (const rational& r1, const rational&r2)

2

這是一種最容易想到的實現方式,在棧上建立物件temp,分子、分母分別相乘後,將之返回。

但仔細再想想,呼叫函式真的能收到這個temp嗎?它是在operator*函式呼叫時的棧上產生的,當這個函式呼叫結束後,棧上的temp也會被pop掉,換言之,temp的生命週期僅存在於operator*函式內,離開這個函式,返回的引用將指向乙個已經不在的物件!

對此,vs編譯器已經給出了warning,如下:

「warning c4172: returning address of local variable or temporary」

千萬不能忽略它。

那既然棧上建立物件不行,還可以在堆上建立嘛(new出來的都是在堆上建立的),於是我們有:

1 friend const rational& operator* (const rational& r1, const rational&r2)

2

這下vs編譯器沒有warning了,之前在資源管理那部分說過,new和delete要配對,這裡只有new,那delete了?delete肯定不能在這個函式裡面做,只能放在外面,這樣new和delete實際位於兩個不同的模組中了,程式設計師很容易忘記**,而且給維護也帶來困難,所以這絕對不是一種好的解決方案。書上舉了乙個例子,比如:

1

rational w, x, y, z;

2 w = x * y * z;

連乘操作會有兩次new的過程,我們很難取得operator*返回的reference背後隱藏的那個指標。

當然,如果把new換成auto_ptr或者是shared_ptr,這種資源洩露的問題就可以避免。

棧上建立的臨時物件不能傳入主調模組,堆上建立的物件就要考慮資源管理的難題,還有其他解決方法嗎?

我們還有static物件可以用,static物件位於全域性靜態區,它的生命週期與這個程式的生命週期是相同的,所以不用擔心它會像棧物件那樣很快消失掉,也不用擔心它會像堆物件那樣有資源洩露的危險。可以像這樣寫:

1 friend const rational& operator* (const rational& r1, const rational&r2)

2

這樣寫編譯器同樣不會報錯,但考慮一下這樣的式子:

1

rational r1, r2, r3;

2if(r1 * r2 == r1 * r3)

if條件恒為真,這就是靜態物件做的!因為所有物件共享這個靜態物件,在執行r1*r2時,temp的值為t1,但執行r1*r3之後,temp的值統一都變成t2了。它在類中只有乙份,明白這個原因後就不難理解了。

既然乙個static物件不行,那弄乙個static陣列?把r1*r2的值放在static陣列的乙個元素裡,而把r1*r3放在static陣列的另乙個元素裡?仔細想想就知道這個想法是多麼的天馬行空。

乙個必須返回新物件的正確寫法是去掉引用,就這麼簡單!

1 friend const rational operator* (const rational& r1, const rational&r2)

2

該讓編譯器複製的時候就要放手去複製,就像花錢買東西一樣,必須花的終究是要花的。

最後總結一下:

絕對不要返回pointer或reference指向乙個local stack物件,指向乙個heap-allocated物件也不是好方法,更不能指向乙個local static物件(陣列),該讓編譯器複製物件的時候,就讓它去複製!

《effective C 》讀書筆記

1,c 關鍵字explicit c 中,乙個引數的 建構函式 或者除了第乙個引數外其餘引數都有預設值的多參建構函式 承擔了兩個角色。1 是個 構造器,2 是個預設且隱含的型別轉換操作符 所以,有時候在我們寫下如 aaa 這樣的 且恰好 的型別正好是aaa單引數構造器的引數型別,這時候 編譯器就自動呼...

Effective C 讀書筆記

一 讓自己習慣c 1 條款01 視c 為聯邦語言 c 的組成可分為四部分 1.c c 仍然以c語言為基礎。區塊 語句 預處理 內建資料型別 陣列 指標等都來自c。2.object oriented c c with classes所訴說的 classes 包括構造和析構 封裝 繼承 多型 virtu...

讀書筆記 Effective C

部分條款過於深奧,部分條款已了然於心,僅記錄當下所識所學 對於常量巨集定義,最好用const代替 define 對於函式巨集定義,最好用inline代替 define include ifdef ifndef仍被需要 內建物件記得手動初始化 使用成員初始列替換賦值操作 以local static替換...