《Effective C 》讀書筆記(四)

2021-07-05 11:09:48 字數 3261 閱讀 4648

模板以前只是學習的時候寫過一些例子,並沒有真正用過。本人對模板還處於超級小白的狀態,基本看不懂這章,所以就先瀏覽一遍吧,等今後有經驗之後,再回頭看一下模板相關的內容。目前打算下一步學一下stl。

a)      classes和templates都支援介面和多型。

b)      對於classses中的介面是顯式的,以函式簽名為中心。多型通過virtual函式發生於執行期。

c)      template中介面是隱式的,多型則通過template具現化和函式過載解析發生於編譯期。

a)      宣告template引數時,字首關鍵字class和typename等價。

b)      使用關鍵字typename標識巢狀從屬型別名稱,但不得在基類列或者初始化列表中作為base class修飾符。

new和delete關鍵字是c++最常用的關鍵字之一,也是最重要的記憶體分配相關的東東,當然有必要很好學習一下。

a)      傳統的new沒有異常處理,如果記憶體分配失敗,那麼就返回null,而新的new在分配出錯的時候,是會丟擲異常的,為了滿足一些老的程式,現在仍然有nothrow new,和老版本的new一樣,但是這樣做並不是很好,因為如果我們new乙個物件,即使分配記憶體沒有出錯,但是建構函式一系列操作還是有可能有異常的。

b)      new-handler簡單來說就是異常處理的乙個函式,我們可以通過std::set_new_handler(函式指標),來設定new的異常處理函式。

c)      windowsgdi程式設計的時候,使用不同的畫筆或自體之前,先儲存起來原來的字型資源(預設的),然後使用自己定義的,使用之後再換回原本的。關於new-handler也可以這樣,先儲存起來原本的new-handler,然後使用自定義的new-handler,最後再換回原來的。這樣,我們就可以給不同的類定義不同的new-handler。

這一條主要是講我們為什麼需要自己寫乙個new和delete,而不是使用c++自帶的new和delete呢?主要有以下幾點:

a)      用來檢測使用時的錯誤,不管是什麼,自己寫的定製版總能增加一些額外的自己想要的功能,比如用來列印log。

b)      為了提公升效能。c++自帶的關鍵字new,雖然能夠申請記憶體,但是這個new是需要照顧各種情況的,小記憶體,大記憶體,短週期,長週期都需要兼顧,所以對於單獨的某種記憶體分配,可能並不是最好的選擇。定製版的new可以加快分配速度,減少記憶體碎片等。

c)      定製版的new和delete可以收集程式記憶體使用的情況。

d)      保證資料型別齊位,有些機器比較苛刻,嚴格要求資料型別位對其,否則程式就會崩潰。有的即使不崩潰,也會降低執行效率。所以,保證資料齊位是很好的增加保險性與效率的方法。還有簇集的概念,當一組內容都位於一塊記憶體時,就可以減少記憶體調頁時缺頁的次數,這也是增加效率的方法。

e)      雖然自定義的new和delete這麼好,但是由於涉及到的內容還是很多,尤其是各種細節,所以,除非能力灰常強,還是不要自己寫了,更好的辦法是使用一些開源或者商業的庫。

知道了為什麼要自己定製new和delete之後,下面就看一下自己定製這兩個操作時需要注意的地方。

a)      首先就是new操作符內部是乙個死迴圈,申請記憶體成功時會跳出迴圈,如果失敗的話,會呼叫new-handler,最後會丟擲bad_alloc異常。

b)      new內部對於申請0位元組記憶體採用的處理方式是改為申請1位元組。

c)      基類的如果被繼承了,那麼使用new的時候,申請的大小很可能不是基類的大小,而是子類的大小。這時候如果不做處理的話肯定會出問題。可以改為如果大小不等於基類,那麼直接改用::operator new(size)即原本的new進行處理。

d)      delete應該進行相關檢測,如果要釋放的指標為null,那麼就不進行處理。

e)      關於delete也應該注意釋放內容大於基類原本大小時的情況。也是可以呼叫::operater new(size)。但是,如果基類的析構函式不是virtual的話,可能傳遞給delete的size大小不正確,所以需要注意析構函式需要是virtual的。

a)      簡單的說,就是不管幹什麼,new和delete都是一對好**,有new的地方就要有對應的delete,而且需要嚴格對應哦!我們自己寫乙個new的時候,有可能加入placement,比如列印log等功能,這時候,就不能再使用原本的new了,需要找乙個相應的delete和其對應。

b)      在我們覆寫了new和delete時要注意名字的覆蓋原則,我們在類中自己定義了new和delete時,原本的new和delete就會被覆蓋。我們需要清楚這一點。如果還想用正常的話,可以使定義的new返回::new()。覆寫這個類的時候,在類中using 基類::operator new。

說來慚愧,能編過就ok,從不看warning的路過…

曾經聽過乙個笑話,在懸崖上立著乙個牌子寫著」warning」,大家走到那裡都很小心,但是乙個程式猿同志卻跳下去了!雖然有點兒冷,不過事實確實如此,我們很大程度上忽略了編譯器苦口婆心的warning,而這些warning確實可能很有用!、

a)      《effective c++》的作者舉了乙個非const函式繼承的時候沒有覆寫基類const函式的例子,這個確實非常非常難以發現。不過我寫了乙個例子,發現編譯器並沒有提醒我任何事,後來,我把警告等級調高之後,發現第一條就是提醒我沒有覆寫成功!看來,是時候看一看警告了,是時候將編譯器的警告級別調高了,爭取獲得再高警告級別下也能寫出少警告的**。、

b)      不要過分依賴編譯器的報警能力,同樣的問題,有的編譯器會報警,而有的卻不會報警。不同的警告級別報告的內容也不同。所以,我們還是要自己提高**的嚴謹性。

c)      當我們真正對警告完全了解的時候,才可以忽視警告,千萬不能看都不看就忽視了!

c++學習到第二個階段,也是時候該進行下一步的學習了。首先,要了解一下c++到底都有什麼,語法熟悉了,常見的技巧也了解了,下面就是一些標準的程式庫了,站在巨人的肩膀上才能看得更遠!

a)      首先就是stl,這也是我下一步最想系統學習的一部分。本人是個演算法渣渣,遇到資料結構就特別蛋疼,一直用的stl的一些基本的資料結構。感覺如果能系統的學習一下stl,今後在面對問題的時候就會有更多種選擇。

b)      還有一些比如iostream,wchar_t,異常處理等等。

c)      tr1並不是乙個標準,而只是乙份文件,真正的東西還是在stl中和boost中。

之前就有聽說過很多關於boost的東東,比如不依賴作業系統的執行緒庫,shared_ptr等等。比如之後c++11標準之後就加入了多執行緒庫,可見,boost庫是c++標準庫的後備軍。

boost中有好多好的東西,並且還在不斷擴充,c++真的是博大精深,沒有五年十年的時間,是不能掌握的。感覺未來的路很長,不過我喜歡!

《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替換...