第一章 從 C 到 C++
條款1 C++是語言聯(lián)邦
這條意思是C++支持面向過程、面向?qū)ο笳⒆颉⒎盒途幊舔撬埂⒑瘮?shù)編程、元編程五中編程方式饵较,但是會令人困惑拍嵌。所以他是一門綜合語言。條款2 const enum inline 代替 define
define不是語言的一部分循诉,而是預(yù)處理的部分横辆。const enum inline可以被編譯器發(fā)現(xiàn)錯誤條款3 使用const來限制出錯的可能
例如返回const引用對象來防止用戶修改。使用const成員函數(shù)來防止對類的破壞茄猫。條款4 使用對象前確保已經(jīng)初始化
主要是使用參數(shù)初始化列表初始化成員或者父類狈蚤。另外如果類使用了全局的對象,則無法知道什么時候初始化的這個對象划纽。所以需要使用類內(nèi)部的static變量脆侮。(也是只有一份)
第二章 有關(guān)對象的構(gòu)造與析構(gòu)
- 條款5 了解對象的默認(rèn)成員函數(shù)
編譯器會根據(jù)需要的時候,默認(rèn)生成的成員函數(shù)包括默認(rèn)構(gòu)造函數(shù)勇劣,拷貝構(gòu)造函數(shù)靖避,析構(gòu)函數(shù),拷貝賦值函數(shù)比默。
其中幻捏,默認(rèn)拷貝賦值函數(shù)會可能無法拷貝引用成員。
條款6 使用=delete來拒絕默認(rèn)生成的成員函數(shù)
這個可以防止類被拷貝命咐,組織拷貝條款7 為多態(tài)基類聲明virtual析構(gòu)函數(shù)
這個是基本功了篡九。條款8 析構(gòu)函數(shù)不要拋出異常
這個可能導(dǎo)致內(nèi)存釋放不完全,或者導(dǎo)致拋出多個異常條款9 構(gòu)造函數(shù)和析構(gòu)函數(shù)中中不調(diào)用虛函數(shù)
這條也比較明顯醋奠,派生類的構(gòu)造函數(shù)如果進入到基類構(gòu)造函數(shù)中榛臼,調(diào)用了虛函數(shù)翰铡,此時派生類的虛函數(shù)還沒有準(zhǔn)備好。條款10 operator = 應(yīng)該返回對象的引用
這樣就可以連續(xù)賦值了條款11 在operator = 處理自我賦值
很難保證你的自我賦值代碼沒有問題讽坏,而且自我賦值是浪費時間的行為。條款12 復(fù)制對象時記得復(fù)制每一個部分
這個很顯然了例证。你要實現(xiàn)賦值函數(shù)路呜,那么就必須拷貝所有內(nèi)容。
第三章 有關(guān)對象的持有資源
條款13 對象是持有資源的基本單位
要能夠獲取資源织咧,還要能夠正確釋放資源胀葱。關(guān)鍵在于使用shared_ptr來管理內(nèi)存◇厦桑可以自動釋放持有的資源條款14 持有資源的對象復(fù)制
要么禁止復(fù)制抵屿,要么使用shared_ptr成員,要么進行深度拷貝捅位,要么使拷貝過程變?yōu)橘Y源的轉(zhuǎn)移轧葛。條款15 持有資源的對象需要提供一個原始對象的方法
這個世界并不完美,許多APIs需要傳遞原始資源的指針才可以艇搀。使用shared_ptr會干擾這個對象的使用方式條款16 new數(shù)組對象的時候需要delete
為了避免這種錯誤尿扯,可以使用vector容器來進行操作,避免對new數(shù)組的需求條款17 new對象作為參數(shù)傳入式可能導(dǎo)致內(nèi)存泄漏
假如new對象和參數(shù)傳入shared_ptr中間拋出了異常焰雕,那么就會導(dǎo)致內(nèi)存泄漏
第四章 設(shè)計與聲明
條款18 讓接口容易被正確使用
接口有的時候難以表述清楚拜轨,比如傳入三個int值庇麦,你得清楚的記得這三個值每一個到底是什么。如果傳入的參數(shù)反了怎么辦?這里書上提到了傳入特定對象以及使用explicit來限定參數(shù)停撞。其實也可以構(gòu)建一個日期對象,然后指定成員绵咱,我感覺這種還好一點备蚓。另外,接口除了參數(shù)要設(shè)置的合理烁峭,返回值也要設(shè)置的合理(比如返回智能指針而不是原始指針強迫對方)晨抡。條款19 設(shè)計class是個大工程
對象的創(chuàng)建、銷毀则剃,對象初始化與對象賦值耘柱,對象通過值拷貝傳遞會異常嗎,新type的合法值是什么棍现。類型轉(zhuǎn)換函數(shù)寫了嗎调煎。operator呢。哪些函數(shù)應(yīng)該被delete己肮?條款20 傳遞常量引用代替?zhèn)髦?br> 傳值會帶來對象的構(gòu)造函數(shù)的調(diào)用士袄,消耗時間悲关,傳遞引用就是傳遞指針
條款21 返回臨時對象時無法返回對臨時對象的引用
如果返回一個由函數(shù)創(chuàng)建的對象時,無法返回對該對象的引用娄柳。編譯器會自己做出正確的優(yōu)化步驟寓辱。條款22 成員變量應(yīng)該聲明為private
如果聲明為public,那么刪除這個變量會導(dǎo)致所有程序重寫赤拒。如果聲明為private秫筏,那么刪除這個變量會導(dǎo)致繼承類程序重寫。所以要聲明為private條款23 使用非成員函數(shù)替換成員函數(shù)
如果一個方法只是調(diào)用了其他幾個成員函數(shù)挎挖,沒有必要將其設(shè)置為成員函數(shù)这敬,把他放在外面,然后用相同的命名空間包裹就可以了條款24 如果成員函數(shù)的參數(shù)需要支持類型轉(zhuǎn)換蕉朵,則將其轉(zhuǎn)為非成員函數(shù)
這是因為成員函數(shù)在某些情況下可能無法發(fā)揮作用崔涂。比如operator *只能支持該類型作為第一個參數(shù)。如果內(nèi)置類型作為第一個參數(shù)的時候就會失效始衅。條款25 swap函數(shù)與異常
swap是個有用的函數(shù)冷蚂。為了實現(xiàn)高效率的swap,你需要設(shè)計一個swap成員函數(shù)來與另外一個對象進行交換汛闸。然后再命名空間設(shè)計一個非成員函數(shù)雨來調(diào)用上面的swap函數(shù)帝雇。最后特化std::swap來讓編譯器選擇你自己的swap
第五章 有關(guān)函數(shù)的實現(xiàn)
條款26 延遲定義出現(xiàn)的順序
C++對于不同行的順序不能隨意更改其順序,這意味著只有用到什么再去定義什么更能符合過程蛉拙,如果在剛開始就將所有的定義尸闸,但是程序一開始就返回,這就會帶來不必要的構(gòu)造與析構(gòu)過程孕锄。條款27 避免類型轉(zhuǎn)換
四種c++類型轉(zhuǎn)換的使用場景雖然可以使用吮廉,但是如果使用了都會帶來更大的問題。舊式的類型轉(zhuǎn)換就更不能用了畸肆。條款28 避免返回handles指向?qū)ο髢?nèi)部成分
盡量避免對象內(nèi)部的數(shù)據(jù)的指針被返回到對象外部宦芦,這會帶來很大的問題。vector []運算符就是這種情況轴脐。這種情況是特例條款29 異常安全
C++異常是最難以處理的一件事情了调卑。但是還是要保證異常。條款30 了解inline
inline是讓編譯器盡量避免棧的展開大咱,而不是一定恬涧。八二法則告訴我們,程序只會花時間在20%的代碼上碴巾,不一定見了函數(shù)就要都用inline溯捆。條款31 減少依賴——定義與聲明相分離
兩種處理方式——實施類與接口類。實施類就是使用另一個類來代理實現(xiàn)該類的功能厦瓢。接口類就是使用面向?qū)ο蟮姆椒▉韺⒃擃愒O(shè)計為接口提揍。
第六章 面向?qū)ο笤O(shè)計
條款32 public繼承意味著is-a關(guān)系
這意味著所有基類能夠辦到的事情派生類也能辦到啤月。但是派生類能夠辦到的基類不一定能辦到條款33 繼承時會發(fā)生名稱遮掩
如果在派生類中聲明了父類函數(shù)的另一個重載版本,會將父類的原始版本也一并覆蓋劳跃,使得無法正確的鏈接到父類函數(shù)谎仲。可以使用using來表示使用父類的函數(shù)空間刨仑。條款34 區(qū)分接口繼承和實現(xiàn)繼承
純虛函數(shù)是只繼承接口郑诺,虛函數(shù)繼承接口和默認(rèn)實現(xiàn),非虛函數(shù)是繼承接口和強制實現(xiàn)條款35 不是只有虛函數(shù)一種實現(xiàn)
可以使用其他設(shè)計模式來代替虛函數(shù)的實現(xiàn)贸人,例如仿函數(shù)條款36 不要重新定義非虛函數(shù)
省的到時候你都不知道具體是哪個被調(diào)用了。沒錯說的就是析構(gòu)函數(shù)佃声。條款37 不要重新定義缺省參數(shù)
這是因為缺省參數(shù)是靜態(tài)確定的而不是動態(tài)確定的艺智。你定義的那個不一定有用條款38 區(qū)分復(fù)合與繼承
public繼承是is-a關(guān)系。復(fù)合是has-a關(guān)系圾亏。例如set的實現(xiàn)十拣,如果繼承l(wèi)ist就會有一些問題了。set應(yīng)該復(fù)合list志鹃。條款39 private繼承意味著根據(jù)其實現(xiàn)
private的使用頻率比復(fù)合使用的頻率要更低夭问。有兩種情況需要這樣實現(xiàn),第一種情況是派生類需要訪問基類的protected成員曹铃。第二種情況是需要重新定義virtual函數(shù)(這種情況難道不應(yīng)該設(shè)計一種中間類嗎)缰趋。條款40 小心的使用多重繼承
多重繼承使用的很少。虛繼承內(nèi)最好不要包含任何成員陕见。因為虛繼承的成員初始化是在派生類內(nèi)完成的秘血。
第七章 泛型編程
條款41 了解隱式接口與編譯器多態(tài)
就是靜態(tài)多態(tài)。條款42 typename的雙重含義
typename除了會在模板的template一行中使用评甜,還會模板的處理中出現(xiàn)灰粮。當(dāng)我們使用成員變量或者是成員類型時,編譯器不知道用的是哪一個忍坷。默認(rèn)使用的成員變量粘舟。加上typename來提醒編譯器用的是成員類型條款43 繼承一個模板類,對模板類內(nèi)的符號要顯示聲明
這是因為模板類可能特化佩研,如果特化柑肴,則可能有的符號不存在。所以需要顯示的指示模板類內(nèi)的符號旬薯,例如使用this指針或者是作用域條款44 template導(dǎo)致代碼膨脹
template參數(shù)在傳入一個非類型參數(shù)的時候嘉抒,會生成多份代碼。這些代碼有一些方式可以避免重復(fù)生成袍暴,但是速度不如原來的快些侍。條款45 運用成員函數(shù)模板接受所有兼容類型
類可以是模板的隶症,成員函數(shù)也可以是模板的。條款46 需要類型轉(zhuǎn)換時請為模板定義非成員函數(shù)
不僅要定義成非成員函數(shù)岗宣,還要定義成為friend函數(shù)蚂会。條款47 使用traits
traits是使用了模板編程與特化的性質(zhì)實現(xiàn)的一個triats類,通過triats類可以獲得想要的泛化類內(nèi)的數(shù)據(jù)類型耗式。條款48 template元編程
元編程指的是在編譯期間就知道結(jié)果的編程方法胁住。比如在編譯期間處理輸入。類似于C++的hello world的程序就是階乘刊咳。
第八章 new 與 delete
條款49
了解new-handler的行為
就是不斷嘗試分配內(nèi)存彪见。我很好奇如果new-handler一直分配失敗會不會出現(xiàn)卡死的現(xiàn)象。條款50
了解自定義new和delete的場合
貌似現(xiàn)在的new和delete性能都很高了娱挨。不用替換條款51
自定義new和delete要保持兼容性條款52
placement new 和placement delete
placement delete會在placement new出現(xiàn)錯誤的時候自動運行
第九章 現(xiàn)在的c++11
條款53
不要忽視warring條款54
熟悉tr1的標(biāo)準(zhǔn)程序庫條款55
熟悉boost