26. Postpone variable definitions as long as possible.
總結:
儘可能延後變數定義式的出現。這樣做可增加程式的清晰度並改善程式效率。
批註:
純C語言此處有衝突,C語言要求變數定義出現在代碼快的開始部分。27. Minimize casting.
1)const_cast 通常被用來將對象的常量性轉除(cast away the constness) 。它也是唯一有此能力的 C++-style 轉型操作符。
2)dynamic_cast主要用來執行"安全向下轉型"( safe downcasting) ,也就是用來決定某對象是否歸屬繼承體系中的某個類型。它是唯一無法由舊式文法執行的動作,也是唯一可能耗費重大運行成本的轉型動作。3)reinterpret_cast 意圖執行低級轉型,實際動作(及結果)可能取決於編譯器,這也就表示它不可移植。例如將一個 pointer to int 轉型為一個 int 。這一類轉型在低級代碼以外很少見。本書只使用一次,那是在討論如何針對原始記憶體 (rawmemory) 寫出一個調試用的分配器 (debugging allocator) 時,見條款50。4)static_cast 用來強迫隱式轉換 (implicit conversions) ,例如將 non-const對象轉為 const 對象(就像條款3 所為) ,或將 int 轉為 double 等等。它也可以用來執行上述多種轉換的反向轉換,例如將void*指標轉為 typed 指標,將pointer-to-base 轉為 pointer-to-derived。但它無掛將 const 轉為 non-canst'一一這個只有const_cast 才辦得到。總結:
第一,如果可以,盡量避免轉型,特別是在注重效率的代碼中避免dynamic_casts。如果有個設計需要轉型動作,試著發展無需轉型的替代設計。
第二,如果轉型是必要的,試著將它隱藏於某個函數背後。客戶隨後可以調用該函數,而不需要將轉型放進他們自己的代碼內。
第三,寧可使用C++-style(新式)轉型,不要使用舊式轉型。前者很容易辨識出來,而且也比較有著分們別類的職掌。28.Avoid returning "handles" to object internals.
總結:避免返回handles(包括references、指標、迭代器)指向對象內部。遵守這個條款可增加封裝性,協助const成員函數的行為像個const,並將發生“虛吊號碼牌”(dangling handles)的可能性將至最低。批註:虛吊號碼牌應該指的就是指向的對象已經被銷毀了,但是返回的指標或者引用還在使用。29.Strive for exception-safe code.當異常被拋出時。帶有異常安全性的函數會:1)不泄露任何資源。2)不允許資料被毀壞。異常安全函數(Exception-safe functions)提供以下三個保證之一:1)基本承諾:如果異常被拋出,程式內的任何事物仍然保持在有效狀態下。2)強烈保證:如果異常被拋出,程式狀態不改變。3)包拋擲(nothrow)保證:承諾絕不拋出異常,因為他們總能完成它們原先承諾的功能。copy and swap原則:為你打算修改的對象(原件)做出一份副本,然後在那副本身上做一切必要修改。若有任何修改動作拋出異常,原對象仍保持未改變狀態。待所有改變都成功後,再將修改過的那個副本和原對象在一個不拋出異常的操作中置換(swap)。總結:第一,異常安全函數(Exception-safe functions)即使發生異常也不會泄漏資源或允許任何資料結構敗壞。這樣的函數區分為三種可能的保證:基本型、強烈型、不拋異常型。第二,“強烈保證”往往能夠以copy-and-swap實現出來,單“強烈保證”並非對所有函數都可實現或具備現實意義。第三,函數提供的“異常安全保證”通常最高只等於其所調用哪個之各個函數的“異常安全保證”中的最弱者。批註:在現實程式的使用中,一般要求達到強烈型即可。因為基本型可能會導致一些不再使用的資料殘留下來。而不拋異常型因為實現過於複雜的原因,一般也不達到這個層級。30.Understand the ins and outs of inlining.inline函數北周的整體觀念是,將“對此函數的每一個調用”都以函數本體替換之。inline函數通常一定被置於標頭檔內,大多數編譯器會在編譯期時候完成inlining,有些編譯器會在連結期完成inlining,甚至有些編譯器會在啟動並執行時候完成inlining.Templates通常也被置於標頭檔中,因為它一旦被使用,編譯器為了將它具體化,需要知道它長什麼樣子。有些編譯器會在連結期才執行template具體化,但是大多數情況下還是在編譯器實現的具體化。一個表面上看似inline的函數是否真是inline,取決於你的建置環境,主要取決於編譯器。大多數的編譯器提供了一個診斷層級:如果它們無法將你要求的函數inline化,會給你一個警告資訊。總結:第一,將大多數inlining限制在小型、被頻繁調用的函數身上。這可使日後的調試過程和二進位升級(binary upgradability)更容易,也可使潛在的代碼膨脹問題最小化,使程式的速度提升機會最大化。第二,不要只因為function templates出現在標頭檔,就將它們聲明為inline。批註:templates和inline沒有必然關係,需要加以區分。31.Minimize compilation dependencies between files.編譯依存關係 compilication dependency連串編譯依存關係 cascading compilation dependencies總結:第一,支援“編譯依存性最小化”的一般構思是:相依於聲明式,不要相依於定義式。基於此構想的兩個手段是Handle classes和Interface classes.第二,程式庫標頭檔應該以“完全且僅有聲明式”(full and declaration-only forms)的形勢存在。這種做法不論是否涉及templates都適用。感悟:這本書對於有一定的代碼量的人會有很大的協助,如果代碼量不夠的話,看起來會覺的很不好理解,也不容易記住這麼多條款。當然,即使代碼量夠了,這本書也不是看一遍就可以扔了的,是屬於可以放在案頭不斷的翻閱,直到這些條款的內容都融入骨髓。這部分的內容,我最大的感受就是很多東西在帶來有利的一面的時候也帶來了不利的一面,所以在使用的過程中要仔細的推敲,到底如何去用。沒有哪種用法就一定萬無一失,就一定會更好,要看具體使用的環境。