純筆記,看多少記多少,不做討論。
第一章 讓自己習(xí)慣C++ ? ?Accustoming Yourself to C++
條款01:視C++為一個(gè)語(yǔ)言聯(lián)邦
View C++ as a federation of languages
C++高效編程守則視狀況而變化,取決于你使用C++的哪一部分。
條款02:盡量以const, enum, inline替換 #define
Prefer consts, enums, and inlines to #defines
對(duì)于單純常量,最好以const對(duì)象或enums替換#defines。
對(duì)于形似函數(shù)的宏(macros),最好改用inline函數(shù)替換#define
條款03:盡可能使用const
Use const whenever possible
將某些東西聲明為const可幫助編譯器偵測(cè)出錯(cuò)誤用法,const可被施加于任何作用域內(nèi)的對(duì)象、函數(shù)參數(shù)、函數(shù)返回類型、成員函數(shù)本體。
編譯器強(qiáng)制實(shí)施bitwise constness,但你編寫(xiě)程序時(shí),應(yīng)該使用“概念上的常量性”(conceptual constness).
當(dāng)const和non-const成員函數(shù)有著實(shí)質(zhì)等價(jià)的實(shí)現(xiàn)時(shí),令non-const版本調(diào)用const版本可避免代碼重復(fù)。
條款04:確定對(duì)象被使用前已先被初始化
Make sure that objects are initialized before they're used
為內(nèi)置型對(duì)象進(jìn)行手工初始化,因?yàn)镃++不保證初始化它們。
構(gòu)造函數(shù)最好使用成員初值列(member initialization list),而不要在構(gòu)造函數(shù)本體內(nèi)使用賦值操作(assignment)。初值列列出的成員變量,其排列次序應(yīng)該和它們?cè)赾lass中的聲明次序相同。
為免除“跨編譯單元之初始化次序”問(wèn)題,請(qǐng)以local static對(duì)象替換non-local static對(duì)象。
========================================
第二章 構(gòu)造/析構(gòu)/賦值運(yùn)算? ? Constructors, Destructors, and Assignment Operators
條款05:了解C++默默編寫(xiě)并調(diào)用哪些函數(shù)
Know what functions C++ silently writes and calls.
編譯器可以暗自為class創(chuàng)建default構(gòu)造函數(shù)、copy構(gòu)造函數(shù)、copy assignment操作符,以及析構(gòu)函數(shù)。
條款06:若不想使用編譯器自動(dòng)生成的函數(shù),就該明確拒絕
Explicitly disallow the use of compiler-generated functions you do not want
為駁回編譯器自動(dòng)(暗自)提供的機(jī)能,可將相應(yīng)的成員函數(shù)申明為private并且不予實(shí)現(xiàn)。使用像Uncopyable這樣的base class也是一種做法。
條款07:為多態(tài)基類申明virtual析構(gòu)函數(shù)
Declare destructors virtual in polymorphic base classes.
polymorphic(帶多態(tài)性質(zhì)的)base classes應(yīng)該聲明一個(gè)virtual析構(gòu)函數(shù)。如果class帶有任何virtual函數(shù),它就應(yīng)該擁有一個(gè)virtual析構(gòu)函數(shù)。
Classes的設(shè)計(jì)目的如果不是作為base classes使用,或不是為了具備多態(tài)性(polymorphically),就不應(yīng)該聲明virtual析構(gòu)函數(shù)。
條款08:別讓異常逃出析構(gòu)函數(shù)
Prevent exceptions from leaving destructors.
析構(gòu)函數(shù)絕對(duì)不要吐出異常。如果一個(gè)被析構(gòu)函數(shù)調(diào)用的函數(shù)可能拋出異常,析構(gòu)函數(shù)應(yīng)該捕捉任何異常,然后吞下它們(不傳播)或結(jié)束程序。
如果客戶需要對(duì)某個(gè)操作函數(shù)運(yùn)行期間拋出的異常做出反應(yīng),那么class應(yīng)該提供一個(gè)普通函數(shù)(而非在析構(gòu)函數(shù)中)執(zhí)行該操作。
條款09:絕不在構(gòu)造和析構(gòu)過(guò)程中調(diào)用virtual函數(shù)
Never call virtual functions during construction or destruction.
在構(gòu)造和析構(gòu)期間不要調(diào)用virtual函數(shù),因?yàn)檫@些類調(diào)用從不下降至derived class(比起當(dāng)前執(zhí)行構(gòu)造函數(shù)和析構(gòu)函數(shù)的那層)。
條款10:令operator=返回一個(gè)reference to *this
Have assignment operators return a reference to *this
令賦值(assignment)操作符返回一個(gè)reference to *this。
條款11:在operator=中處理“自我賦值”
Handle assignment to self in operator=.
確保黨對(duì)象自我賦值時(shí)operator=有良好的行為。其中技術(shù)包括比較“來(lái)源對(duì)象”和“目標(biāo)對(duì)象”的地址、精心周到的語(yǔ)句順序、以及copy-and-swap。
確定任何函數(shù)如果操作一個(gè)以上的對(duì)象,而其中多個(gè)對(duì)象是同一個(gè)對(duì)象時(shí),其行為仍然正確。
條款12:復(fù)制對(duì)象時(shí)勿忘其每一個(gè)成分
Copy all parts of an object
Copying函數(shù)應(yīng)該確保復(fù)制“對(duì)象內(nèi)的所有成員變量”及“所有base class成分”。
不要嘗試以某個(gè)copying函數(shù)實(shí)現(xiàn)另一個(gè)copying函數(shù)。應(yīng)該將共同機(jī)能放進(jìn)第三個(gè)函數(shù)中,并由兩個(gè)copying函數(shù)共同調(diào)用。
========================================
第三章 資源管理? ? Resource Management
條款13:以對(duì)象管理資源
Use objects to manage resources.
為防止資源泄露,請(qǐng)使用RAII(Resource Acquisition Is Initialization: RAII)對(duì)象,它們?cè)跇?gòu)造函數(shù)中獲得資源并在析構(gòu)函數(shù)中釋放資源。
兩個(gè)常被使用的RAII classes分別是tr1::shared_ptr和auto_ptr。前者通常是較佳選擇,因?yàn)槠鋍opy行為比較直觀。若選擇auto_ptr,復(fù)制動(dòng)作會(huì)使它(被復(fù)制物)指向null。
條款14:在資源管理類中小心copying行為
Think carefully about copying behavior in resource-managing classes.
復(fù)制RAII對(duì)象必須一并復(fù)制它所管理的資源,所以資源的copying行為決定RAII對(duì)象的copying行為。
普遍而常見(jiàn)的RAII class copying行為是:抑制copying行為、實(shí)施引用計(jì)數(shù)法(reference counting)。不過(guò)其他行為也都可能被實(shí)現(xiàn)。
條款15:在資源管理類中提供對(duì)原始資源的訪問(wèn)
Provide access to raw resources in resources-managing classes.
APIs往往要求訪問(wèn)原始資源(raw resources),所以每一個(gè)RAII classes應(yīng)該提供一個(gè)“取得其所管理之資源”的辦法。
對(duì)原始資源的訪問(wèn)可能經(jīng)由顯示轉(zhuǎn)換或隱式轉(zhuǎn)換。一般而言顯示轉(zhuǎn)換比較安全,但隱式轉(zhuǎn)換對(duì)客戶比較方便。
條款16:成對(duì)使用new和delete時(shí)要采取相同形式
Use the same form in corresponding uses of new and delete.
如果你在new表達(dá)式中使用[],必須在相應(yīng)的delete表達(dá)式中也使用[]。如果你在new表達(dá)式中不使用[],一定不要在相應(yīng)的delete表達(dá)式中使用[]。
條款17:以獨(dú)立語(yǔ)句將newed對(duì)象置入智能指針
Store newed objects in smart pointers in standalone statements.
//未完成閱讀章節(jié)
以獨(dú)立語(yǔ)句將newed對(duì)象存儲(chǔ)于(置入)智能指針內(nèi)。如果不這樣做,一旦異常被拋出,有可能導(dǎo)致難以察覺(jué)的資源泄露。
========================================
第四章 設(shè)計(jì)與聲明? ? Designs and Declarations
條款18:讓接口容易被正確使用,不易被誤用
Make interfaces easy to use correctly and hard to use incorrectly.
好的接口很容易被正確使用,不容易被誤用。你應(yīng)該在你的所有接口中努力達(dá)成這些性質(zhì)。
“促進(jìn)正確使用”的辦法包括接口的一致性,以及與內(nèi)置類型的行為兼容。
“阻止誤用”的辦法包括建立新類型、限制類型上的操作,束縛對(duì)象值,以及消除客戶的資源管理責(zé)任。
trl::shared_ptr支持定制型刪除器(custom deleter)。這可以防范DLL問(wèn)題,可被用來(lái)自動(dòng)解除互斥鎖(mutexes;見(jiàn)條款14)等等。
條款19:設(shè)計(jì)class猶如設(shè)計(jì)type
Treat class design as type design.
Class的設(shè)計(jì)就是type的設(shè)計(jì)。在定義一個(gè)新type之前,請(qǐng)確定你已經(jīng)考慮過(guò)本條款覆蓋的所有討論主題。
新type的對(duì)象應(yīng)該如何被創(chuàng)建和銷毀?
對(duì)象的初始化和對(duì)象的賦值應(yīng)該有什么樣的差別?
新type的對(duì)象如果被passed by value(以值傳遞)意味著什么?
什么是新type的“合法值”?
你的新type需要配合某個(gè)繼承圖系(inheritance graph)嗎?
你的新type需要什么樣的轉(zhuǎn)換?
什么樣的操作符和函數(shù)對(duì)此新type而言是合理的?
什么樣的標(biāo)準(zhǔn)函數(shù)應(yīng)該駁回?
誰(shuí)該取用新type的成員?
什么是新type的“未聲明接口”(undeclared interface)?
你的新type有多么一般化?
你真的需要一個(gè)新type嗎?
條款20:寧以pass-by-reference-to-const替換pass-by-value
Prefer pass-by-reference-to-const to pass-by-value
盡量以pass-by-reference-to-const替換pass-by-value。前者通常比較高效,并可避免切割問(wèn)題(slicing problem)。
以上規(guī)則并不適用于內(nèi)置類型,以及STL的迭代器和函數(shù)對(duì)象。對(duì)它們而言,pass-by-value往往比較適當(dāng)。
條款21:必須返回對(duì)象時(shí),別妄想返回其reference
Don't try to return a reference when you must return an object.
絕不要返回pointer或reference指向一個(gè)local stack對(duì)象,或返回reference指向一個(gè)heap-allocated對(duì)象,或返回pointer或reference指向一個(gè)local static對(duì)象而有可能同時(shí)需要多個(gè)這樣的對(duì)象。條款4已經(jīng)為“在單線程環(huán)境中合理返回reference指向一個(gè)local static對(duì)象”提供了一份設(shè)計(jì)實(shí)例。
條款22:將成員變量聲明為private
Declare data members private
切記將成員變量聲明為private。這可賦予客戶訪問(wèn)數(shù)據(jù)的一致性、可細(xì)微劃分訪問(wèn)控制、允諾約束條件獲得保證,并提供class作者以充分的實(shí)現(xiàn)彈性。
protected并不比public更具封裝性。