[More Effective C++ 學習筆記]效率

來源:互聯網
上載者:User

<效率>

 

       條款16:謹記80 – 20 法則

       80 – 20 法則說:一個程式80 % 的資源用於20 % 的代碼身上。

       語句的執行次數和函數調用次數可以間接協助你瞭解你無法直接量測的軟體行為。如果你無法直接量測動態記憶體的使用,那麼知道記憶體配置函數和釋放函數被調用的頻率,至少也可以給你帶來一部分的聯想。

 

       條款17:考慮使用lazy evaluation(緩式評估)

       一旦你採用lazy evaluation,就是以某種方式撰寫你的classes,使它們延緩運算,直到那些運算結果刻不容緩地被迫切需要為止。

       在const memberr functions內修改data members的最好方法是,將成員變數聲明為mutable,意思就是這樣的欄位可以再任何member function內被修改,甚至是在const member functions內。

 

       條款18:分期攤還預期的計算成本

       當你必須支援某些運算而其結果並不是總是需要的時候,lazy evaluation可以改善程式。當你必須支援某些運算而結果幾乎總是被需要,或者其結果常常被多次需要的時候,over-eager evalution可以改善程式效率。

       over-eager evaluation背後的觀念是,如果你預期程式常常會用到某個計算,你可以降低每次計算的平均成本,辦法就是設計一份資料結構以便能夠既有效率地處理需求。其方式是:

  1. 將已計算好而有可能再被需要的數值保留下來,即caching;
  2. prefetching。

 

  條款19:瞭解臨時對象的來源

  C++中真正的臨時兌現是不可見的,即不會在你的原始碼中出現。只要你產生一個non-heap object而沒有為它命名,便誕生了一個臨時變數。

  臨時變數通常發生於兩種情況:

  1. 當隱式轉換型別轉換(implicit type conversions)被施行起來以求函數調用成功;
  2. 當函數返回對象的時候。

 

  為了讓函數調用得成功而產生的臨時對象發生在於,傳遞某對象給一個函數,而其型別與它即將綁定上去的參數型別不同的時候。

  只有當對象以by value方式傳遞,或是當對象被傳遞給一個reference-to-const參數時,這些轉換才會發生。如果對象被傳遞給一個reference-to-non-const參數,並不會發生此類轉換。

  當程式員期望非臨時對象被修改,此時如果編譯器針對reference-to-non-const對象進行隱式型別轉換,會允許臨時對象被改變。

 

       條款20:協助完成傳回值最佳化(Return value optimization)

       如果函數一定得以by-value方式返回對象,可以通過返回所謂的constructor arguments以取代對象。這樣做能夠讓編譯器消除臨時對象的成本。

       傳回值最佳化:利用函數的return點消弭一個局部臨時對象。如果該類函數作為內嵌函式,並且考慮到內嵌函式的特性的話,傳回值最佳化類似於建構函式的調用。

       條款21:利用多載技術避免隱式型別轉換

       C++存在許多遊戲規則,其中一條就是:每個重載操作符必須接獲至少一個使用者定製型別的自變數。

 

       條款22:考慮以操作符複合形式(op=)代替其獨身形式(op)

       一個有效實現操作符重載的方式是,以操作符複合形式為基礎實現其獨身形式。

 

       三個與效率有關的情況值得注意:

  1. 獨身形式的操作符通過必須返回一個新對象,因此程式必須負擔一個臨時對象(局部對象)的構造和析構;而複合形式的則直接將結果寫入其左端自變數,所以不需要產生一個臨時對象來放置傳回值;
  2. 如果同時提供某個操作符的複合版和獨身版,你便允許你的客戶在效率與便利性之間做取捨;
  3. 考慮傳回值最佳化問題。

 

  在C++中,未具名對象總是比具有名對象更容易被消除。所以當你面臨具名對象(局部變數)或臨時對象的抉擇時,最好選擇臨時對象。

 

  條款24:瞭解virtual functions、multiple inheritance、virtual base classes、runtime type identification的成本

       vtbl(virtual table)通常是一個由函數指標架構而成的數組。程式中每一個class凡聲明(或繼承)虛函數者,都有自己的一個vtbl,而其中的條目(entries)就是該class的各個虛函數實現體的指標。

       如果類C2整合基類C1,然後重新定義某些繼承而來的虛函數,並加上新的虛函數。其vtbl內的條目(entries)將會指向對應於對象型別的各個適當函數,以及未被C2重新定義的C1虛函數。

 

       virtual table pointer(vptr)的任務是可以指示每個對象相應於哪個vtbl。通過引用或指標調用虛函數,編譯器必須產生代碼來完成如下動作:

  1. 根據對象的vptr找出其vtbl。成本只有一個位移調整(offset adjustment,以便獲得vptr)和一個指標間接動作(以便獲得vtbl);
  2. 找出被調用該函數在vtbl內對應指標。編譯器會為每個虛函數指定了一個獨一無二的索引,因此本步驟的成本只是一個差移以求進入vtbl數組;
  3. 調用步驟2所得指標所指向的函數。

 

  需要注意內嵌函式和虛函數的區別:

  1. 內聯(inline)意味著在編譯期,將調用端的調用動以被調用函數的函數本體取代之(宏定義的函數化);
  2. 虛函數(virtual)意味著等待,直到運行期才知道那個函數被調用。

 

  在多重繼承情況下,一個對象之內包含多個vptrs(每個基類各對應一個)。在non-virtual base classes的情況下,如果derived class之於其base class有多條繼承路徑,則此base class的data member會在每一個derived class object體內複製滋生,每一個副本對應derived class和base class之內的一條繼承路線。讓base class成為virtual的話,可以消除這樣的複製現象。

       但是,virutal base classes可能招致另一個成本,因為其實現做法常常利用指標,指向virtual base class成分以消除複製行為,而你的對象內可能出現一個(或多個)這樣的指標。

 

       RTTI(runtime type identification)讓我們得以在運行期獲得objects和classes的相關資訊,這些資訊被存放在型別為type_info的對象內。可以利用typeid操作符取得某個class響應的type_info對象。

 

 

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.