STL容器的本質

2022-04-20 07:57:02 字數 2428 閱讀 4999

最近在學習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》為我們提供了一些使用原則:

你需要「可以在容器的任意位置插入乙個新元素」的能力嗎?如果是,你需要序列容器,關聯容器做不到。

你關心元素在容器中的順序嗎?如果不,雜湊容器就是可行的選擇。否則,你要避免使用雜湊容器。

必須使用標準c++中的容器嗎?如果是,就可以除去雜湊容器、slist和rope。

你需要哪一類迭代器?如果必須是隨機訪問迭代器,在技術上你就只能限於vector、deque和string,但你也可能會考慮rope(關於 rope的更多資訊在條款50)。如果需要雙向迭代器,你就用不了slist(參見條款50)和雜湊容器的一般實現(參見條款25)。

當插入或者刪除資料時,是否非常在意容器內現有元素的移動?如果是,你就必須放棄連續記憶體容器(參見條款5)。

容器中的資料的記憶體布局需要相容c嗎?如果是,你就只能用vector(參見條款16)。

查詢速度很重要嗎?如果是,你就應該看看雜湊容器(參見條款25),排序的vector(參見條款23)和標準的關聯容器——大概是這個順序。

你介意如果容器的底層使用了引用計數嗎?如果是,你就得避開string,因為很多string的實現是用引用計數(參見條款13)。你也不能用 rope,因為權威的rope實現是基於引用計數的(參見條款50)。於是你得重新審核你的string,你可以考慮使用vector 。

你需要插入和刪除的事務性語義嗎?也就是說,你需要有可靠地回退插入和刪除的能力嗎?如果是,你就需要使用基於節點的容器。如果你需要多元素插入 (比如,以範圍的方式——參見條款5)的事務性語義,你就應該選擇list,因為list是唯一提供多元素插入事務性語義的標準容器。事務性語義對於有興 趣寫異常安全**的程式設計師來說非常重要。(事務性語義也可以在連續記憶體容器上實現,但會有乙個效能開銷,而且**不那麼直觀。要了解這方面的知識,請參考 sutter的《exceptional c++》的條款17[8]。)

你要把迭代器、指標和引用的失效次數減到最少嗎?如果是,你就應該使用基於節點的容器,因為在這些容器上進行插入和刪除不會使迭代器、指標和引用失效(除非它們指向你刪除的元素)。一般來說,在連續記憶體容器上插入和刪除會使所有指向容器的迭代器、指標和引用失效。

你需要具有有以下特性的序列容器嗎:1)可以使用隨機訪問迭代器;2)只要沒有刪除而且插入只發生在容器結尾,指標和引用的資料就不會失效?這個 乙個非常特殊的情況,但如果你遇到這種情況,deque就是你夢想的容器。(有趣的是,當插入只在容器結尾時,deque的迭代器也可能會失 效,deque是唯一乙個「在迭代器失效時不會使它的指標和引用失效」的標準stl容器。) 

這些問題幾乎不是事情的完結。比如,它們沒有關注不同的容器型別使用不同的記憶體配置策略(條款10和14討論了這些策略的一些方面)。但是,它們 已經足夠是你信服了,除非你對元素順序、標準的一致性、迭代器能力、記憶體布局和c的相容性、查詢速度、因為引用計數造成的行為不規則、事務性語義的輕鬆實 現和迭代器失效的條件沒興趣,你得在容器操作的演算法複雜度上花更多的考慮時間。當然這樣的複雜度是重要的,但這離整個故事很遠。

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

C 容器(STL容器)

容器 container 用於存放資料的類模板。可變長陣列 鍊錶 平衡二叉樹等資料結構在stl中都被實現為容器。在使用容器時,即將容器類模型例項化為容器類,會指明容器中存放的元素是什麼型別。容器可以分為兩大類 順序容器和關聯容器 順序容器有可變長動態陣列vector 雙端佇列deque 雙向鍊錶li...

STL容器的選擇

標準stl序列容器 vector string deque和list。標準stl關聯容器 set multiset map和multimap。非標準序列容器slist和rope。slist是乙個單向鍊錶,rope本質上是乙個重型字串。繩子 rope 是重型的 線 string 明白了嗎?你可以找到乙...

stl 的容器總結

優先佇列簡單容器 stack 棧 queue 佇列 deque 雙端佇列 priority queue優先佇列 list 鍊錶 vector 向量 map對映 set 幾何 stack 先進後出 queue 先進先出 這是兩個最基礎的容器具體的操作只有 push pop size empty deq...