Effective stl---筆記

1 只有序列容器支持push_front或push_back,
  只有關聯容器支持count和lower_bound,等等.

2 (條款1解釋了deque是惟一一個在迭代器失效的
    狀況下指針和引用仍然有效的東西)  【不做爲特例】

3 迭代器/指針/參考的失效規則

4 typedef代碼封裝
    typedef vector<Widget> WidgetContainer;
    typedef WidgetContainer::iterator WCIterator;
    WidgetContainer cw;
  更高等級的封裝,限制權限,使用class CustomList含有List

5 nth_element算法  【讓第n+1大/小的數據,出如今v[n],且它是數據的大小分水嶺,兩邊數據不保證有序】


6  拷進去,拷出來。這就是STL的方式。是的,拷貝對象是STL的方式。

7 基類對象容器,固然因爲繼承的存在,拷貝會致使分割。【splice】

8 咱們也能夠創建一個能夠足夠包含maxNumWidgets個Widget的空vector,但沒有構造Widget:
  vector<Widget> vw;
  vw.reserve(maxNumWidgets); // reserve的詳細信息請參見條款14
  【比數組文明多了(數組直接用默認構造函數構造對象了)】
 
9 儘可能調用empty(splice致使不能常數時間知道size是否爲0,必需要去計數)【區間插入?】

10 第一,它提供給我一個機會來提醒你assign成員函數的存在,
   太多的程序員沒注意到這是一個很方便的方法。
   它對於全部標準序列容器(vector,string,deque和list)都有效。
   【替代數據集】
   
 11 v1.clear();
    copy(v2.begin() + v2.size() / 2, v2.end(), back_inserter(v1));
    寫這些仍然比寫assign的調用要作更多的工做。
    此外,雖然在這段代碼中沒有表現出循環,在copy中的確存在一個循環(參見條款43)。
    結果,效率損失仍然存在。在這裏,我要離題一下來指出幾乎全部目標區間是經過
    插入迭代器(好比,經過inserter,back_inserter或front_inserter)指定的copy的使用
    均可以——應該——經過調用區間成員函數來代替。
    好比這裏,這個copy的調用能夠用一個insert的區間版本代替:
    v1.insert(v1.end(), v2.begin() + v2.size() / 2, v2.end());

12 通常來講使用區間成員函數能夠輸入更少的代碼。
   區間成員函數會致使代碼更清晰更直接了當。

13  ● 區間構造。全部標準容器都提供這種形式的構造函數:
   container::container(InputIterator begin, // 區間的起點
                        InputIterator end); // 區間的終點

    若是傳給這個構造函數的迭代器是istream_iterators或istreambuf_iterators(參見條款29),
    你可能會遇到C++的最驚異的解析,緣由之一是你的編譯器可能會由於把這個構造看做一個函數
    聲明而不是一個新容器對象的定義而中斷。條款6告訴你須要知道全部關於解析的東西,包括怎麼對付它。
   ● 區間插入。全部標準序列容器都提供這種形式的insert:
    void container::insert(iterator position, // 區間插入的位置
                           InputIterator begin, // 插入區間的起點
                           InputIterator end); // 插入區間的終點
    關聯容器使用它們的比較函數來決定元素要放在哪裏,因此它們了省略position參數。
    void container::insert(lnputIterator begin, InputIterator end);

    當尋找用區間版本代替單元素插入的方法時,不要忘記有些單元素變量用採用不一樣的函數名假裝它們本身。
    好比,push_front和push_back都把單元素插入容器,即便它們不叫insert。若是你看見一個循環調用push_front或
    push_back,或若是你看見一個算法——好比copy——的參數是front_inserter或者back_inserter,你就發現了一個
    insert的區間形式應該做爲優先策略的地方。

   ● 區間刪除。每一個標準容器都提供了一個區間形式的erase,可是序列和關聯容器的返回類型不一樣。
     序列容器提供了這個:
     iterator container::erase(iterator begin, iterator end);
     而關聯容器提供這個:
     void container::erase(iterator begin, iterator end);程序員


  爲何不一樣?解釋是若是erase的關聯容器版本返回一個迭代器(被刪除的那個元素的下一個)會招致一個沒法
      接受的性能降低。我是衆多發現這個徒有其表的解釋的人之一,但標準說的就是標準說的,標準說erase的序列
  和關聯容器版本有不一樣的返回類型。算法


  這個條款的對insert的性能分析大部分也一樣能夠用於erase。單元素刪除的函數調用次數仍然大於一次調用區間
  刪除。當使用單元素刪除時,每一次元素值仍然必須向它們的目的地移動一位,而區間刪除能夠在一個單獨的
  移動中把它們移動到目標位置。編程


  關於vector和string的插入和刪除的一個論點是必須作不少重複的分配。(固然對於刪除,會發生重複的回收。)
  那是由於用於vector和string的內存自動增加來適應於新元素,但當元素的數目減小時它不自動收縮。(條款17描
  述了你怎麼減小被vector或string持有的沒必要要的內存。)
  一個很是重要的區間erase的表現是erase-remove慣用法。你能夠在條款32瞭解到全部關於它的信息。
   ● 區間賦值。就像我在這個條款的一開始提到的,全部標準序列容器都提供了區間形式的assign:
  void container::assign(InputIterator begin, InputIterator end);
  因此如今咱們明白了,儘可能使用區間成員函數來代替單元素兄弟的三個可靠的論點。設計模式

      區間成員函數更容易寫,它們更清楚地表達你的意圖,並且它們提供了更高的性能。那是很難戰勝的三駕馬車。



14 ifstream dataFile("ints.dat");
     istream_iterator<int> dataBegin(dataFile);
     istream_iterator<int> dataEnd;
     list<int> data(dataBegin, dataEnd);
    命名迭代器對象的使用和普通的STL編程風格相反,可是你得判斷這種方法對編譯器和必須使用編譯器的人
    都模棱兩可的代碼是一個值得付出的代價。數組

    【注意stream相似的迭代器,都給予命名】

15 它們能告訴你所容納的對象類型(經過value_type的typedef)

16 銷燬new 使用foreach  和 模板函數對象
   struct xx
   {
     template<typename T>
     void operator()(const T *p) const
     {
        delete p;
        //p = NULL; //置null沒意義,且是const,當心屢次delete
     }
   }
   
   若是在foreach以前拋異常,可使用智能指針boost shared_ptr來避免泄漏。
   
17  若是你有一個連續內存容器(vector、deque或string——參見條款1),安全

     最好的方法是erase-remove慣用法(參見條款32):
  c.erase(remove(c.begin(), c.end(), 1963), // 當c是vector、string
                                                         c.end()); // 或deque時,
                    // erase-remove慣用法
                    // 是去除特定值的元素
                    // 的最佳方法
  這方法也適合於list,可是,正如條款44解釋的,list的成員函數remove更高效:
  c.remove(1963); // 當c是list時,
        // remove成員函數是去除
        // 特定值的元素的最佳方法數據結構

  對於關聯容器,解決問題的適當方法是調用erase:
   c.erase(1963);     // 當c是標準關聯容器時
              // erase成員函數是去除
              // 特定值的元素的最佳方法


18  由於它爲vector、string和deque產生未定義的行爲!要記得對於那樣的容器,多線程

調用erase不只使全部指向被刪元素的迭代器失效,也使被刪元素以後的全部迭代器失效。less


19 若是咱們觀察在本條款中提到的全部東西,咱們得出下列結論:函數

● 去除一個容器中有特定值的全部對象:
若是容器是vector、string或deque,使用erase-remove慣用法。
若是容器是list,使用list::remove。
若是容器是標準關聯容器,使用它的erase成員函數。
● 去除一個容器中知足一個特定斷定式的全部對象:
若是容器是vector、string或deque,使用erase-remove_if慣用法。
若是容器是list,使用list::remove_if。
若是容器是標準關聯容器,使用remove_copy_if和swap,或寫一個循環來遍歷容器元素,當你把迭代器傳給erase時記得後置遞增它。
● 在循環內作某些事情(除了刪除對象以外):
若是容器是標準序列容器,寫一個循環來遍歷容器元素,每當調用erase時記得都用它的返回值更新你的迭代器。
若是容器是標準關聯容器,寫一個循環來遍歷容器元素,當你把迭代器傳給erase時記得後置遞增它。


20  當涉及到線程安
全和STL容器時,你能夠肯定庫實現容許在一個容器上的多讀取者和不一樣容器上的多寫入者

【使用鎖 RAII機制在構造函數裏上鎖(傳容器爲參數)】

21 3. 你必須確保只delete一次。若是一個分配被刪除了不止一次,結果也會未定義。
   【屢次delete空不會產生問題】
   
22 string使用引用計數的話,多線程下不安全。能夠用vector<char> 替代。
  【對於多線程,咱們應該設計儘可能避免競態條件,此是根本,謹慎設計共享變量】

23 使用reserve來避免沒必要要的從新分配

24 事實上,讓C風格API把數據放入一個vector,而後拷到你實際想要的STL容器中的主意老是有效的。
   【同理,能夠將stl容器經過vector再轉回C Api中,vector是橋】
   
   if( !v.empty() )
   {
     dosomething(&v[0],v.size()); //不要用v.begin()
   }

25 vector<Contestant>(contestants).swap(contestants); ???
   因此當你想對vector和string進行「收縮到合適」時,就考慮「交換技巧」。
   string().swap(s); // 清除s並且最小化它的容量
   
26 標準庫提供了兩個替代品,它們能知足幾乎全部須要。第一個是deque<bool>。deque提供了幾乎全部vector所
提供的(惟一值得注意的是reserve和capacity),而deque<bool>是一個STL容器,它保存真正的bool值。當
然,deque內部內存不是連續的。因此不能傳遞deque<bool>中的數據給一個但願獲得bool數組的C API[1](參
見條款16),但你也不能讓vector<bool>作這一點,由於沒有可移植的取得vector<bool>中數據的方法。
   
   【vector<bool>不知足STL容器的必要條件,你最好不要使用它。】
   【vector<bool>的位域實現。】
   
   若是不在意沒有迭代器和動態改變大小,你也許會發現bitset正合你意。
   
27 《綠野仙蹤》。全世界最有名的童話
片之一,榮獲1939年奧斯卡最佳電影歌曲和最佳電影配樂。其中的多色馬,關聯容器是不一樣顏色的生物。真
的,它們共享了序列容器的不少特性,但它們在不少基本方法上不一樣

28 find
對「相同」的定義是相等,基於operator==。set::insert對「相同」的定義是等價,一般基於operator<。
等價通常在每種標準關聯容器(好比,set、multiset、map
和multimap)的一部分——排序順序方面有意義

29 。set<Widget>的默認比較函數是less<Widget>,而默認的less<Widget>簡單地對Widget調用
operator<,因此w1和w2關於operator<有等價的值若是下面表達式爲真:
!(w1 < w2) // w1 < w2時它非真
&& // 並且
!(w2<w1) // w2 < w1時它非真

在通常狀況下,用於關聯容器的比較函數不是operator<或甚至less,它是用戶定義的判斷式。(關於判斷式的
更多信息參見條款39。)每一個標準關聯容器經過它的key_comp成員函數來訪問排序判斷式,因此若是下式求
值爲真,兩個對象x和y關於一個關聯容器c的排序標準有等價的值:
!c.key_comp()(x, y) && !c.key_comp()(y, x) // 在c的排序順序中
// 若是x在y以前它非真,
// 同時在c的排序順序中
// 若是y在x以前它非真


30  if (ciss.find("persephone") != ciss.end())... // 這個測試會成功
但若是咱們用非成員的find算法,搜索會失敗:
if (find(ciss.begin(), ciss.end(),
"persephone") != ciss.end())... // 這個測試會失敗
那是由於「persephone」等價於「Persephone」(關於比較仿函數CIStringCompare),但不等於它(由於string
("persephone") != string("Persephone"))。這個例子演示了爲何你應該跟隨條款44的建議優先選擇成員函數
(就像set::find)而不是非成員兄弟(就像find)的一個理由。
容器的比較函數對象。算法find用的==

31 經過只使用一個比較函數並使用等價做爲兩個值「相等」的意義的仲裁者

32 你應該回憶起
set<string*> ssp;
是這個的簡寫:
set<string*, less<string*> > ssp;
好,爲了徹底準確,它是
set<string*, less<string*>, allocator<string*> > ssp;

33 使人遺憾的是,stringPtrLess不是一種類型,它是一個
函數。這就是爲何嘗試使用stringPtrLess做爲set的比較函數不能編譯的緣由,set不要一個函數,它要的是能在內部用實例化創建函數的一種類型。
 【for_each可使用函數】
 
 struct DereferenceLess {
      template <typename PtrType>
      bool operator()(PtrType pT1, // 參數是值傳遞的,
                      PtrType pT2) const // 由於咱們但願它們
      { // 是(或行爲像)指針
                 return *pT1 < *pT2;
      }
};

34 比較函數總應該對相等的值返回false。


35 強制類型轉換,產生一個臨時對象
  if (i != se.end()) {                             // 同上,
        ((Employee)(*i)).setTitle("Corporate Deity"); // 但使用C
}                                                // 強轉語法
【相似於】
if (i != se.end()){
         Employee tempCopy(*i); // 把*i拷貝到tempCopy
         tempCopy.setTitle("Corporate Deity"); // 修改tempCopy
}    

36 若是你要老是能夠工做並且老是安全地改變set、multiset、
    map或multimap裏的元素,按五個簡單的步驟去作:
1. 定位你想要改變的容器元素。若是你不肯定最好的方法,條款45提供了關於怎樣進行適當搜尋的指導。
2. 拷貝一份要被修改的元素。對map或multimap而言,肯定不要把副本的第一個元素聲明爲const。畢竟,你想要改變它!
3. 修改副本,使它有你想要在容器裏的值。
4. 從容器裏刪除元素,一般經過調用erase(參見條款9)。
5. 把新值插入容器。若是新元素在容器的排序順序中的位置正好相同或相鄰於刪除的元素,使用insert的「提示」形式把插入的效率從對數時間改進到分攤的常數時間。使用你從第一步得到的迭代器做爲提示。


37  EmpIDSet se; // 同前,se是一個以ID號
// 排序的僱員set
Employee selectedID; // 同前,selectedID是一個帶有
// 須要ID號的僱員
...
EmpIDSet::iterator i =
se.find(selectedID);          // 第一步:找到要改變的元素
if (i!=se.end()){
Employee e(*i);               // 第二步:拷貝這個元素
se.erase(i++);               // 第三步:刪除這個元素;
                             // 自增這個迭代器以
                              // 保持它有效(參見條款9)
e.setTitle("Corporate Deity"); // 第四步:修改這個副本
se.insert(i, e);              // 第五步:插入新值;提示它的位置
                              // 和原先元素的同樣
}
你將原諒我以這種方法放它,但要記得關鍵的事情是對於set和multiset,若是你進行任何容器元素的原地修改,你有責任確保容器保持有序

【原地修改不要修改set的key】

38 一旦你寫了DataCompare,東西都很好的依序排列了。而一旦位置合適了,只要你的程序按照
101頁描述的階段方式使用數據結構,它們每每比相應的使用真的map的設計運行得更快並且使用更少內存。
若是你的程序不是按照階段的方式操做數據結構,那麼使用有序vector代替標準關聯容器幾乎能夠肯定是在
浪費時間。

39 若是你要更新已存在的map元素,operator[]更好,但若是你要增
  加一個新元素,insert則有優點。
【人如其名】

40 儘可能用iterator代替const_iterator,reverse_iterator和
const_reverse_iterator

41 由於它可能花費線性時間的代價來產生一個和const_iterator等價的iterator,而且由於若是不能訪問
const_iterator所屬的容器這個操做就沒法完成。從這個角度出發,也許你須要從新審視你從const_iterator產生
iterator的設計。事實上那樣的考慮幫助激發了條款26,它建議你當處理容器時儘可能用iterator代替const和reverse迭代器。

42 reverse_iterator的base成員函數返回一個「對應的」iterator的說法並不許確。對於插入操
做而言,的確如此;可是對於刪除操做,並不是如此。當須要把reverse_iterator轉換成iterator的時候,有一點非
常重要的是你必須知道你準備怎麼處理返回的iterator,由於只有這樣你才能決定你獲得的iterator是不是你需
要的。
【並非真正對着同一個位置】

43 當你瞭解它以後,你也應該考慮把ostreambuf_iterator用於相應的無格式一個一個字符輸出的做。它們沒有了
ostream_iterator的開銷(和靈活性),因此它們一般也作得更好。

44
不管什麼時候你使用一個要求指定目的區間的算法,確保目的區間已經足夠大或者在算法執行時能夠增長大小。

若是你選擇增長大小,就使用插入迭代器,

好比ostream_iterators或從back_inserter、front_inserter或inserter返回的迭代器。

這是全部你須要記住的東西。


45

● 若是你須要在vector、string、deque或數組上進行徹底排序,你可使用sort或stable_sort。
● 若是你有一個vector、string、deque或數組,你只須要排序前n個元素,應該用partial_sort。
● 若是你有一個vector、string、deque或數組,你須要鑑別出第n個元素或你須要鑑別出最前的n個元素,
             而不用知道它們的順序,nth_element是你應該注意和調用的。
● 若是你須要把標準序列容器的元素或數組分隔爲知足和不知足某個標準,你大概就要找partition或stable_partition。
● 若是你的數據是在list中,你能夠直接使用partition和stable_partition,你可使用list的sort來代替sort和stable_sort。

若是你須要partial_sort或nth_element提供的效果,你就必須間接完成這個任務,但正如我在上面勾畫的,會有不少選擇。

46 須要更少資源(時間和空間)的算法列在須要更多的前面:
  1. Partition

  2. stable_partition

  3. nth_element

  4. partial_sort
   5. sort
   6. stable_sort

47 一旦你知道了remove不能「真的」從一個容器中刪除東西,和erase聯合使用就變成理所固然了。你要記住的
  惟一其餘的東西是remove不是惟一這種狀況的算法。另外有兩種「相似remove」的算法:remove_if和unique。
  remove和remove_if之間的類似性很直截了當。因此我不會細講,但unique行爲也像remove。它用來從一個區
  間刪除東西(鄰近的重複值)而不用訪問持有區間元素的容器。結果,若是你真的要從容器中刪除元素,你
  也必須成對調用unique和erase,unique在list中也相似於remove。

  正像list::remove真的刪除東西(並且比eraseremove慣用法高效得多)。

  list::unique也真的刪除鄰近的重複值(也比erase-unique高效)。
  【成員函數好,成員函數好】


48 無論你怎麼選擇處理動態分配指針的容器,經過引用計數智能指針、在調用相似remove的算法前手動刪除和
  廢棄指針或者一些你本身發明的技術,本條款的指導意義依然同樣:提防在指針的容器上使用相似remove的算法。

  沒有注意這個建議的人只能形成資源泄漏
【remove的機制形成】

49 我知道大家中的一部分會用蠻力記憶,因此這裏有一個只能操做有序數據的算法的表:
  binary_search lower_bound
  upper_bound equal_range
  set_union set_intersection
  set_difference set_symmetric_difference
  merge inplace_merge
  includes

50 11個名字帶「copy」的算法:
  copy copy_backward
  replace_copy reverse_copy
  replace_copy_if unique_copy
  remove_copy rotate_copy
  remove_copy_if partial_sort_copy
  unintialized_copy

51 用accumulate或for_each來統計區間

52 BPFC::operator()的實現例證了BPFC全部的虛函數是怎麼實現的:它們調用了在BPFCImpl中它們真的虛函
  數。結果是仿函數類(BPFC)是小而單態的,但能夠訪問大量狀態並且行爲多態。
  我在這裏忽略了不少細節,由於我勾勒出的基本技術在C++圈子中已經廣爲人知了。《Effective C++》的條款34中有。

  在Gamma等的《設計模式》[6]中,這叫作「Bridge模式」。Sutter在他的《Exceptional C++》[8]中叫它「Pimpl慣用法」.
  從STL的視角看來,要記住的最重要的東西是使用這種技術的仿函數類必須支持合理方式的拷貝。若是你是
  上面BPFC的做者,你就必須保證它的拷貝構造函數對指向的BPFCImpl對象作了合理的事情。也許最簡單的合理的東西是引用計數,使用  相似Boost的shared_ptr,你能夠在條款50中瞭解它.
  實際上,對於本條款的目的,惟一你必須擔憂的是BPFC的拷貝構造函數的行爲,由於當在STL中被傳遞或從
  一個函數返回時,函數對象老是被拷貝——值傳遞,記得嗎?那意味着兩件事。讓它們小,並且讓它們單態。



53 (not一、not二、bind1st和bind2nd)都須要存在某些typedef

54  這是STL裏的一個廣泛習慣:函數和函數對象總使用用於非成員函數

  的語法形式調用

55  瞭解使用ptr_fun、mem_fun和mem_fun_ref的緣由


56 不要經過把less的定義當兒戲來誤導那些程序員。若是你使用less(明確或者隱含),保證它表示operator<。
  若是你想要使用一些其餘標準排序對象,創建一個特殊的不叫作less的仿函數類


57
  ● 效率:算法一般比程序員產生的循環更高效。
  ● 正確性:寫循環時比調用算法更容易產生錯誤。
  ● 可維護性:算法一般使代碼比相應的顯式循環更乾淨、更直觀。

58  
    幾乎不可能被戰勝的sort及其同族算法(好比,
    stable_sort(),nth_element()等,參見條款31);適用於有序區間的搜索算法(好比,binary_search,
    lower_bound等,參見條款34和35)也同樣好;就算是很平凡的任務,好比從連續內存容器中除去一些對象,
    使用erase-remove慣用法都比絕大多數程序員寫的循環更高效
   【儘可能使用stl提供的算法,人那是計算機科學家寫的】


59  在算法調用與手寫循環正在進行的較量中,關於代碼清晰度的底線是:這徹底取決於你想在循環裏作的是什
    麼。若是你要作的是算法已經提供了的,或者很是接近於它提供的,調用泛型算法更清晰。若是循環裏要作
   的事很是簡單,但調用算法時卻須要使用綁定和適配器或者須要獨立的仿函數類,你恐怕仍是寫循環比較
    好。最後,若是你在循環裏作的事至關長或至關複雜,天平再次傾向於算法。由於長的、複雜的一般總應該
   封裝入獨立的函數。只要將循環體一封裝入獨立函數,你幾乎總能找到方法將這個函數傳給一個算法(一般
   是for_each),以使得最終代碼直截了當。

   只要能用高層次的術語——如insert、find和for_each,

   取代了低層次的詞彙——如for、while和do,咱們就提高了軟件的【【抽象】】層次

60  當面臨着STL算法和同名的容器成員函數間進行選擇時,你應該儘可能使用成員函數。幾
      乎能夠確定它更高效,並且它看起來也和容器的慣常行爲集成得更好。
【私人定製服務】

61 count和find是線性時間的,但有序區間的

    搜索算法(binary_search、lower_bound、upper_bound和equal_range)是對數時間的。

62 我會簡單地說明count和 find算法都用相等來搜索,

      而binary_search、lower_bound、upper_bound和equal_range則用等價


63 lower_bound回答這個問題:「它在嗎?若是
是,第一個拷貝在哪裏?若是不是,它將在哪裏?」
保持比
較函數同步不是火箭發射,但倒是另外一個要記住的東西,並且我想你已經有不少須要你記的東西了。


64 使用equal_range。equal_range返回一對迭代器,第一個等於lower_bound返回的迭代
器,第二個等於upper_bound返回的(也就是,等價於要搜索值區間的末迭代器的下一個)。所以,
equal_range,返回了一對劃分出了和你要搜索的值等價的區間的迭代器。一個名字很好的算法,不是嗎?


65 一般咱們有一個容器,而不是一個區間。在這種狀況下,咱們必須區別序列和關聯容器。對於標準的序列容器(vector、string、deque和list),你
應該遵循我在本條款提出的建議,使用容器的begin和end迭代器來劃分出區間。
這種狀況對標準關聯容器(set、multiset、map和multimap)來講是不一樣的,由於它們提供了搜索的成員函
數,它們每每是比用STL算法更好的選擇。條款44詳細說明了爲何它們是更好的選擇,簡要地說,是由於
它們更快行爲更天然。幸運的是,成員函數一般和相應的算法有一樣的名字,因此前面的討論推薦你使用的
算法count、find、equal_range、lower_bound或upper_bound,在搜索關聯容器時你均可以簡單的用同名的成員
函數來代替。
調用binary_search的策略不一樣,由於這個算法沒有提供對應的成員函數。要測試在set或map中是否存在某個
值,使用count的慣用方法來對成員進行檢測:
。。。。
要測試某個值在multiset或multimap中是否存在,find每每比count好,由於一旦找到等於指望值的單個對象,
find就能夠停下了,而count,在最遭的狀況下,必須檢測容器裏的每個對象。(對於set和map,這不是問
題,由於set不容許重複的值,而map不容許重複的鍵。)
可是,count給關聯容器計數是可靠的。特別,它比調用equal_range而後應用distance到結果迭代器更好。首
先,它更清晰:count 意味着「計數」。第二,它更簡單;不用創建一對迭代器而後把它的組成(譯註:就
條款45:注意count、find、binary_search、lower_bound、upper_bound和equal_range的區別
是first和second)傳給distance。第三,它可能更快一點。

你想知道的
使用的算法使用的成員函數
在無序區間在有序區間在set或map上在multiset或multimap上
指望值是否存在? find binary_search count find
指望值是否存在?
若是有,第一個等
於這個值的對象在
哪裏?
find equal_range find find或lower_bound(參見下面)
第一個不在指望值
以前的對象在哪
裏?
find_if lower_bound lower_bound lower_bound
第一個在指望值之
後的對象在哪裏?
find_if upper_bound upper_bound upper_bound
有多少對象等於期
望值?
count equal_range,而後distance count count
等於指望值的全部
對象在哪裏?
find(迭代) equal_range equal_range equal_range


66 把函數對象做爲算法的參數所帶來的不只是巨大的效率提高。在讓你的代碼能夠編譯方面,它們也更穩健。
固然,真函數頗有用,可是當涉及有效的STL編程時,函數對象常常更有用。
  【他們可能會內聯,而普通函數是函數指針,每次的指針調用】   67 寫可讀性高的代碼 68 在這裏,它叫作_Tree,但我知道的其餘實現使用__tree或__rb_tree,後者反映出 使用紅-黑樹——在STL實現中最常使用的平衡樹類型。

相關文章
相關標籤/搜索