STL容器的本質

http://blog.sina.com.cn/s/blog_4d3a41f40100eof0.htmlhtml

最近在學習unordered_map裏面的散列函數和相等函數怎麼寫.學習過程當中看到了一個好帖子.學習學習程序員

 

標準STL序列容器:vector、string、deque和list
標準STL關聯容器:set、multiset、map和multimap算法

非標準序列容器slist和rope
非標準關聯容器hash_set、hash_multiset、hash_map和hash_multimap數組

rope是繩子的意思,string是線的意思,rope就是一個重量級的string安全

STL不一樣容器的實現是差異很大的,但它們都有一個數據結構原型,都具有各自的特性,最明顯的是同一方法在不一樣容器中的效率差異很大。所以認清STL經常使用容器的本質,你纔不會在你的應用中選錯容器。數據結構

std::list的本質是鏈表
它的優點是在頭和尾巴的插入和刪除很快速
它的缺點就是隨機訪問能力差,由於它是挨個訪問元素的
若是你的應用對隨機訪問效率有較高要求,那list不是你的首選。最誇張的是list的size()是從頭至尾挨個數一遍的函數

std::vector的本質是紅黑樹(一種特殊的平衡二叉樹)
它的優勢是隨機訪問能力強,紅黑樹的緣由
它的缺點是非最後一個元素的插入和刪除速度慢,爲了保證隨機訪問速度,插入和刪除對會對紅黑樹作調整
通常狀況下咱們把vector當成一個數組使用,只不過這個數組的大小能夠增長,因此不要貪心只用這些功能就夠了。貪心你就會形成效率的下降。
vector容量的增加也是有開銷的,若是你頻繁的push_back(),還不如先一次性的多分配一些reserve()。注意reserve()和resize()是不同的,一個調整預留空間,一個是調整元素個數。佈局

(此部分會繼續更新)性能

此外《Effective+STL》爲咱們提供了一些使用原則:學習

  1. 你須要「能夠在容器的任意位置插入一個新元素」的能力嗎?若是是,你須要序列容器,關聯容器作不到
  2. 你關心元素在容器中的順序嗎?若是不,散列容器就是可行的選擇。不然,你要避免使用散列容器。
  3. 必須使用標準C++中的容器嗎?若是是,就能夠除去散列容器、slist和rope。
  4. 你須要哪一類迭代器?若是必須是隨機訪問迭代器,在技術上你就只能限於vector、deque和string,但你也可能會考慮rope(關於 rope的更多信息在條款50)。若是須要雙向迭代器,你就用不了slist(參見條款50)和散列容器的通常實現(參見條款25)。
  5. 當插入或者刪除數據時,是否很是在乎容器內現有元素的移動?若是是,你就必須放棄連續內存容器(參見條款5)。
  6. 容器中的數據的內存佈局須要兼容C嗎?若是是,你就只能用vector(參見條款16)。
  7. 查找速度很重要嗎?若是是,你就應該看看散列容器(參見條款25),排序的vector(參見條款23)和標準的關聯容器——大概是這個順序。
  8. 你介意若是容器的底層使用了引用計數嗎?若是是,你就得避開string,由於不少string的實現是用引用計數(參見條款13)。你也不能用 rope,由於權威的rope實現是基於引用計數的(參見條款50)。因而你得從新審覈你的string,你能夠考慮使用vector <char>。
  9. 你須要插入和刪除的事務性語義嗎?也就是說,你須要有可靠地回退插入和刪除的能力嗎?若是是,你就須要使用基於節點的容器。若是你須要多元素插入 (好比,以範圍的方式——參見條款5)的事務性語義,你就應該選擇list,由於list是惟一提供多元素插入事務性語義的標準容器。事務性語義對於有興 趣寫異常安全代碼的程序員來講很是重要。(事務性語義也能夠在連續內存容器上實現,但會有一個性能開銷,並且代碼不那麼直觀。要了解這方面的知識,請參考 Sutter的《Exceptional C++》的條款17[8]。)
  10. 你要把迭代器、指針和引用的失效次數減到最少嗎?若是是,你就應該使用基於節點的容器,由於在這些容器上進行插入和刪除不會使迭代器、指針和引用失效(除非它們指向你刪除的元素)。通常來講,在連續內存容器上插入和刪除會使全部指向容器的迭代器、指針和引用失效。
  11. 你須要具備有如下特性的序列容器嗎:1)可使用隨機訪問迭代器;2)只要沒有刪除並且插入只發生在容器結尾,指針和引用的數據就不會失效?這個 一個很是特殊的狀況,但若是你遇到這種狀況,deque就是你夢想的容器。(有趣的是,當插入只在容器結尾時,deque的迭代器也可能會失 效,deque是惟一一個「在迭代器失效時不會使它的指針和引用失效」的標準STL容器。) 
  12. 這些問題幾乎不是事情的完結。好比,它們沒有關注不一樣的容器類型使用不一樣的內存配置策略(條款10和14討論了這些策略的一些方面)。可是,它們 已經足夠是你信服了,除非你對元素順序、標準的一致性、迭代器能力、內存佈局和C的兼容性、查找速度、由於引用計數形成的行爲不規則、事務性語義的輕鬆實 現和迭代器失效的條件沒興趣,你得在容器操做的算法複雜度上花更多的考慮時間。固然這樣的複雜度是重要的,但這離整個故事很遠。

在程序的世界裏面,也是有得必有失,沒有完美的東西,你所要決定的是在開發效率和運行效率間找一個平衡。而這個的前提是你要熟悉你所用的東西。

相關文章
相關標籤/搜索