最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Effective C++:改善程序與設(shè)計的55個具體做法

2021-09-15 17:00 作者:C語言編程__Plus  | 我要投稿

高效程序員必看技巧!


(1)視 C++ 為一個語言聯(lián)邦(C、Object-Oriented C++、Template C++、STL)

(2)可以編譯器替換預(yù)處理器(盡量以?const、enum、inline?替換?#define)

(3)盡可能使用 const

(4)確定對象被使用前已先被初始化(構(gòu)造時賦值(copy 構(gòu)造函數(shù))比 default 構(gòu)造后賦值(copy assignment)效率高)

(5)了解 C++ 默默編寫并調(diào)用哪些函數(shù)(編譯器暗自為 class 創(chuàng)建 default 構(gòu)造函數(shù)、copy 構(gòu)造函數(shù)、copy assignment 操作符、析構(gòu)函數(shù))

(6)若不想使用編譯器自動生成的函數(shù),就應(yīng)該明確拒絕(將不想使用的成員函數(shù)聲明為 private,并且不予實(shí)現(xiàn))

(7)為多態(tài)基類聲明 virtual 析構(gòu)函數(shù)(如果 class 帶有任何 virtual 函數(shù),它就應(yīng)該擁有一個 virtual 析構(gòu)函數(shù))

(8)別讓異常逃離析構(gòu)函數(shù)(析構(gòu)函數(shù)應(yīng)該吞下不傳播異常,或者結(jié)束程序,而不是吐出異常;如果要處理異常應(yīng)該在非析構(gòu)的普通函數(shù)處理)

(9)絕不在構(gòu)造和析構(gòu)過程中調(diào)用 virtual 函數(shù)(因?yàn)檫@類調(diào)用從不下降至 derived class)

(10)令?operator=?返回一個?reference to *this?(用于連鎖賦值)

(11)在?operator=?中處理 “自我賦值”

(12)賦值對象時應(yīng)確保復(fù)制 “對象內(nèi)的所有成員變量” 及 “所有 base class 成分”(調(diào)用基類復(fù)制構(gòu)造函數(shù))

(13)以對象管理資源(資源在構(gòu)造函數(shù)獲得,在析構(gòu)函數(shù)釋放,建議使用智能指針,資源取得時機(jī)便是初始化時機(jī)(Resource Acquisition Is Initialization,RAII))

(14)在資源管理類中小心 copying 行為(普遍的 RAII class copying 行為是:抑制 copying、引用計數(shù)、深度拷貝、轉(zhuǎn)移底部資源擁有權(quán)(類似 auto_ptr))

(15)在資源管理類中提供對原始資源(raw resources)的訪問(對原始資源的訪問可能經(jīng)過顯式轉(zhuǎn)換或隱式轉(zhuǎn)換,一般而言顯示轉(zhuǎn)換比較安全,隱式轉(zhuǎn)換對客戶比較方便)


(16)成對使用 new 和 delete 時要采取相同形式(new?中使用?[]?則?delete [],new?中不使用?[]?則?delete)

(17)以獨(dú)立語句將 newed 對象存儲于(置入)智能指針(如果不這樣做,可能會因?yàn)榫幾g器優(yōu)化,導(dǎo)致難以察覺的資源泄漏)

(18)讓接口容易被正確使用,不易被誤用(促進(jìn)正常使用的辦法:接口的一致性、內(nèi)置類型的行為兼容;阻止誤用的辦法:建立新類型,限制類型上的操作,約束對象值、消除客戶的資源管理責(zé)任)

(19)設(shè)計 class 猶如設(shè)計 type,需要考慮對象創(chuàng)建、銷毀、初始化、賦值、值傳遞、合法值、繼承關(guān)系、轉(zhuǎn)換、一般化等等。

(20)以 pass-by-reference-to-const 替換 pass-by-value (前者通常更高效、避免切割問題(slicing problem),但不適用于內(nèi)置類型、STL迭代器、函數(shù)對象)

(21)必須返回對象時,別妄想返回其 reference(絕不返回 pointer 或 reference 指向一個 local stack 對象,或返回 reference 指向一個 heap-allocated 對象,或返回 pointer 或 reference 指向一個 local static 對象而有可能同時需要多個這樣的對象。)

(22)將成員變量聲明為 private(為了封裝、一致性、對其讀寫精確控制等)

(23)以 non-member、non-friend 替換 member 函數(shù)(可增加封裝性、包裹彈性(packaging flexibility)、機(jī)能擴(kuò)充性)

(24)若所有參數(shù)(包括被this指針?biāo)傅哪莻€隱喻參數(shù))皆須要類型轉(zhuǎn)換,請為此采用 non-member 函數(shù)

(25)考慮寫一個不拋異常的 swap 函數(shù)

(26)盡可能延后變量定義式的出現(xiàn)時間(可增加程序清晰度并改善程序效率)

(27)盡量少做轉(zhuǎn)型動作(舊式:(T)expression、T(expression);新式:const_cast<T>(expression)、dynamic_cast<T>(expression)、reinterpret_cast<T>(expression)、static_cast<T>(expression)、;盡量避免轉(zhuǎn)型、注重效率避免 dynamic_casts、盡量設(shè)計成無需轉(zhuǎn)型、可把轉(zhuǎn)型封裝成函數(shù)、寧可用新式轉(zhuǎn)型)

(28)避免使用 handles(包括 引用、指針、迭代器)指向?qū)ο髢?nèi)部(以增加封裝性、使 const 成員函數(shù)的行為更像 const、降低 “虛吊號碼牌”(dangling handles,如懸空指針等)的可能性)

(29)為 “異常安全” 而努力是值得的(異常安全函數(shù)(Exception-safe functions)即使發(fā)生異常也不會泄露資源或允許任何數(shù)據(jù)結(jié)構(gòu)敗壞,分為三種可能的保證:基本型、強(qiáng)列型、不拋異常型)

(30)透徹了解 inlining 的里里外外(inlining 在大多數(shù) C++ 程序中是編譯期的行為;inline 函數(shù)是否真正 inline,取決于編譯器;大部分編譯器拒絕太過復(fù)雜(如帶有循環(huán)或遞歸)的函數(shù) inlining,而所有對 virtual 函數(shù)的調(diào)用(除非是最平淡無奇的)也都會使 inlining 落空;inline 造成的代碼膨脹可能帶來效率損失;inline 函數(shù)無法隨著程序庫的升級而升級)


(31)將文件間的編譯依存關(guān)系降至最低(如果使用 object references 或 object pointers 可以完成任務(wù),就不要使用 objects;如果能夠,盡量以 class 聲明式替換 class 定義式;為聲明式和定義式提供不同的頭文件)

(32)確定你的 public 繼承塑模出 is-a(是一種)關(guān)系(適用于 base classes 身上的每一件事情一定適用于 derived classes 身上,因?yàn)槊恳粋€ derived class 對象也都是一個 base class 對象)

(33)避免遮掩繼承而來的名字(可使用 using 聲明式或轉(zhuǎn)交函數(shù)(forwarding functions)來讓被遮掩的名字再見天日)

(34)區(qū)分接口繼承和實(shí)現(xiàn)繼承(在 public 繼承之下,derived classes 總是繼承 base class 的接口;pure virtual 函數(shù)只具體指定接口繼承;非純 impure virtual 函數(shù)具體指定接口繼承及缺省實(shí)現(xiàn)繼承;non-virtual 函數(shù)具體指定接口繼承以及強(qiáng)制性實(shí)現(xiàn)繼承)

(35)考慮 virtual 函數(shù)以外的其他選擇(如 Template Method 設(shè)計模式的 non-virtual interface(NVI)手法,將 virtual 函數(shù)替換為 “函數(shù)指針成員變量”,以?tr1::function?成員變量替換 virtual 函數(shù),將繼承體系內(nèi)的 virtual 函數(shù)替換為另一個繼承體系內(nèi)的 virtual 函數(shù))

(36)絕不重新定義繼承而來的 non-virtual 函數(shù)

(37)絕不重新定義繼承而來的缺省參數(shù)值,因?yàn)槿笔?shù)值是靜態(tài)綁定(statically bound),而 virtual 函數(shù)卻是動態(tài)綁定(dynamically bound)

(38)通過復(fù)合塑模 has-a(有一個)或 “根據(jù)某物實(shí)現(xiàn)出”(在應(yīng)用域(application domain),復(fù)合意味 has-a(有一個);在實(shí)現(xiàn)域(implementation domain),復(fù)合意味著 is-implemented-in-terms-of(根據(jù)某物實(shí)現(xiàn)出))

(39)明智而審慎地使用 private 繼承(private 繼承意味著 is-implemented-in-terms-of(根據(jù)某物實(shí)現(xiàn)出),盡可能使用復(fù)合,當(dāng) derived class 需要訪問 protected base class 的成員,或需要重新定義繼承而來的時候 virtual 函數(shù),或需要 empty base 最優(yōu)化時,才使用 private 繼承)

(40)明智而審慎地使用多重繼承(多繼承比單一繼承復(fù)雜,可能導(dǎo)致新的歧義性,以及對 virtual 繼承的需要,但確有正當(dāng)用途,如 “public 繼承某個 interface class” 和 “private 繼承某個協(xié)助實(shí)現(xiàn)的 class”;virtual 繼承可解決多繼承下菱形繼承的二義性問題,但會增加大小、速度、初始化及賦值的復(fù)雜度等等成本)

(41)了解隱式接口和編譯期多態(tài)(class 和 templates 都支持接口(interfaces)和多態(tài)(polymorphism);class 的接口是以簽名為中心的顯式的(explicit),多態(tài)則是通過 virtual 函數(shù)發(fā)生于運(yùn)行期;template 的接口是奠基于有效表達(dá)式的隱式的(implicit),多態(tài)則是通過 template 具現(xiàn)化和函數(shù)重載解析(function overloading resolution)發(fā)生于編譯期)

(42)了解 typename 的雙重意義(聲明 template 類型參數(shù)是,前綴關(guān)鍵字 class 和 typename 的意義完全相同;請使用關(guān)鍵字 typename 標(biāo)識嵌套從屬類型名稱,但不得在基類列(base class lists)或成員初值列(member initialization list)內(nèi)以它作為 base class 修飾符)

(43)學(xué)習(xí)處理模板化基類內(nèi)的名稱(可在 derived class templates 內(nèi)通過?this->?指涉 base class templates 內(nèi)的成員名稱,或藉由一個明白寫出的 “base class 資格修飾符” 完成)

(44)將與參數(shù)無關(guān)的代碼抽離 templates(因類型模板參數(shù)(non-type template parameters)而造成代碼膨脹往往可以通過函數(shù)參數(shù)或 class 成員變量替換 template 參數(shù)來消除;因類型參數(shù)(type parameters)而造成的代碼膨脹往往可以通過讓帶有完全相同二進(jìn)制表述(binary representations)的實(shí)現(xiàn)類型(instantiation types)共享實(shí)現(xiàn)碼)

(45)運(yùn)用成員函數(shù)模板接受所有兼容類型(請使用成員函數(shù)模板(member function templates)生成 “可接受所有兼容類型” 的函數(shù);聲明 member templates 用于 “泛化 copy 構(gòu)造” 或 “泛化 assignment 操作” 時還需要聲明正常的 copy 構(gòu)造函數(shù)和 copy assignment 操作符)


(46)需要類型轉(zhuǎn)換時請為模板定義非成員函數(shù)(當(dāng)我們編寫一個 class template,而它所提供之 “與此 template 相關(guān)的” 函數(shù)支持 “所有參數(shù)之隱式類型轉(zhuǎn)換” 時,請將那些函數(shù)定義為 “class template 內(nèi)部的 friend 函數(shù)”)

(47)請使用 traits classes 表現(xiàn)類型信息(traits classes 通過 templates 和 “templates 特化” 使得 “類型相關(guān)信息” 在編譯期可用,通過重載技術(shù)(overloading)實(shí)現(xiàn)在編譯期對類型執(zhí)行 if...else 測試)

(48)認(rèn)識 template 元編程(模板元編程(TMP,template metaprogramming)可將工作由運(yùn)行期移往編譯期,因此得以實(shí)現(xiàn)早期錯誤偵測和更高的執(zhí)行效率;TMP 可被用來生成 “給予政策選擇組合”(based on combinations of policy choices)的客戶定制代碼,也可用來避免生成對某些特殊類型并不適合的代碼)

(49)了解 new-handler 的行為(set_new_handler 允許客戶指定一個在內(nèi)存分配無法獲得滿足時被調(diào)用的函數(shù);nothrow new 是一個頗具局限的工具,因?yàn)樗贿m用于內(nèi)存分配(operator new),后繼的構(gòu)造函數(shù)調(diào)用還是可能拋出異常)

(50)了解 new 和 delete 的合理替換時機(jī)(為了檢測運(yùn)用錯誤、收集動態(tài)分配內(nèi)存之使用統(tǒng)計信息、增加分配和歸還速度、降低缺省內(nèi)存管理器帶來的空間額外開銷、彌補(bǔ)缺省分配器中的非最佳齊位、將相關(guān)對象成簇集中、獲得非傳統(tǒng)的行為)


(51)編寫 new 和 delete 時需固守常規(guī)(operator new 應(yīng)該內(nèi)涵一個無窮循環(huán),并在其中嘗試分配內(nèi)存,如果它無法滿足內(nèi)存需求,就應(yīng)該調(diào)用 new-handler,它也應(yīng)該有能力處理 0 bytes 申請,class 專屬版本則還應(yīng)該處理 “比正確大小更大的(錯誤)申請”;operator delete 應(yīng)該在收到 null 指針時不做任何事,class 專屬版本則還應(yīng)該處理 “比正確大小更大的(錯誤)申請”)

(52)寫了 placement new 也要寫 placement delete(當(dāng)你寫一個 placement operator new,請確定也寫出了對應(yīng)的 placement operator delete,否則可能會發(fā)生隱微而時斷時續(xù)的內(nèi)存泄漏;當(dāng)你聲明 placement new 和 placement delete,請確定不要無意識(非故意)地遮掩了它們地正常版本)

(53)不要輕忽編譯器的警告

(54)讓自己熟悉包括 TR1 在內(nèi)的標(biāo)準(zhǔn)程序庫(TR1,C++ Technical Report 1,C++11 標(biāo)準(zhǔn)的草稿文件)

(55)讓自己熟悉 Boost(準(zhǔn)標(biāo)準(zhǔn)庫)

以上

寫在最后:對于準(zhǔn)備學(xué)習(xí)C/C++編程的小伙伴,如果你想更好的提升你的編程核心能力(內(nèi)功)不妨從現(xiàn)在開始!

微信公眾號:C語言編程學(xué)習(xí)基地

整理分享(多年學(xué)習(xí)的源碼、項(xiàng)目實(shí)戰(zhàn)視頻、項(xiàng)目筆記,基礎(chǔ)入門教程)

歡迎轉(zhuǎn)行和學(xué)習(xí)編程的伙伴,利用更多的資料學(xué)習(xí)成長比自己琢磨更快哦!


Effective C++:改善程序與設(shè)計的55個具體做法的評論 (共 條)

分享到微博請遵守國家法律
襄垣县| 莫力| 柯坪县| 资源县| 名山县| 淮滨县| 兴山县| 三门峡市| 明光市| 来宾市| 舟山市| 五指山市| 防城港市| 龙山县| 镇沅| 林西县| 天门市| 宜兰市| 延庆县| 页游| 新龙县| 凤冈县| 天门市| 隆子县| 北票市| 霞浦县| 开远市| 瑞安市| 麻栗坡县| 江津市| 历史| 乐至县| 阿城市| 舞钢市| 丘北县| 阿荣旗| 收藏| 即墨市| 民和| 鹿邑县| 蛟河市|