STL 配置器和容器,序列容器和關聯容器總結

2021-07-05 03:17:03 字數 2454 閱讀 9956

stl中定義了許多容器型別,這些型別在c++中非常實用。但是很多人卻並沒有理解為什麼叫配置器和容器,下面做個總結:

vector: **實現為一塊連續的記憶體,可以理解為動態擴張的array,具有隨機訪問的特性。但是不適合頻繁的隨機插入、刪除。

list: **實現為雙向鍊錶結構,適合頻繁隨機插入、刪除的操作。

deque: 雙向操作佇列,**實現比較複雜。利用乙個map表(非stl的map,而是類似於指標陣列),用作塊對映,每個位址都指向一塊連續的記憶體,每個連續記憶體大小相同。deque內部通過迭代器start,finish分別指向第乙個塊和最後乙個塊。

stack:棧的特性是單向操作,同乙個入口、出口,filo。在stl中,由於deque具有雙向操作的功能,所以沒必要單獨再去實現一套stack。只需要在deque的基礎上封閉一端的操作,就具備了stack的特性。因此,stack是乙個adapter。

queue:佇列的特性是fifo,一端進一端出。同樣在deque的基礎上,分別關閉一端的input和另一端的output,就具備了queue的特性。所以,queue也是乙個adapter。

heap:作為演算法呈現。實現的是堆排序,裡面包含了vector。

priority-queue

:包含了heap,用來實現優先順序排序。

可以看出,實際上queue、stack的底層實現跟deque是一樣的。由一段段的定量連續空間組成。

(1)為何map和set的插入刪除效率比用其他序列容器高?

大部分人說,很簡單,因為對於關聯容器來說,不需要做記憶體拷貝和記憶體移動。說對了,確實如此。set容器內所有元素都是以節點的方式來儲存,其節點結構和鍊錶差不多,指向父節點和子節點。結構圖可能如下:

a/ \

b c/ \ / \

d e f g

因此插入的時候只需要稍做變換,把節點的指標指向新的節點就可以了。刪除的時候類似,稍做變換後把指向刪除節點的指標指向其他節點也ok了。這裡的一切操作就是指標換來換去,和記憶體移動沒有關係。

(2)為何每次insert之後,以前儲存的iterator不會失效?

iterator這裡就相當於指向節點的指標,記憶體沒有變,指向記憶體的指標怎麼會失效呢(當然被刪除的那個元素本身已經失效了)。相對於vector來說,每一次刪除和插入,指標都有可能失效,呼叫push_back在尾部插入也是如此。因為為了保證內部資料的連續存放,iterator指向的那塊記憶體在刪除和插入過程中可能已經被其他記憶體覆蓋或者記憶體已經被釋放了。即使時push_back的時候,容器內部空間可能不夠,需要一塊新的更大的記憶體,只有把以前的記憶體釋放,申請新的更大的記憶體,複製已有的資料元素到新的記憶體,最後把需要插入的元素放到最後,那麼以前的記憶體指標自然就不可用了。特別時在和find等演算法在一起使用的時候,牢記這個原則:不要使用過期的iterator。

所以,對於set、map、list而言,當客戶端對它進行元素insert、delete操作時,操作之前的迭代器,在操作完成後依然有效(被刪除的元素除外)。但是對於vector,則需要保證iterator不要過期。

(3)當資料元素增多時,set的插入和搜尋速度變化如何?

對於set/map其實都是呼叫stl底層的rb-tree來實現,對於rb-tree,我們知道它的插入、刪除效率很高,logn。所以對於大量元素的場景也是很適用。許多檔案系統、分布式排程,都是利用紅黑樹的查詢特性,儲存索引或節點資訊。

set 元素不可修改?

set 作為集合,儲存的元素只有乙個值,value就是key,key也是value。一般情況,set的值是唯讀的,不可以修改。但是並不一定。需要根據sgi stl的版本,具體分析。

筆者用的版本就是可以通過迭代器修改值的。

ite1 = iset.find(23);

if (ite1 != iset.end())

};typedef _pr value_compare;

typedef _k key_type;

typedef _pr key_compare;

typedef _a allocator_type;

typedef _tree<_k, value_type, _kfn, _pr, _a> _imp;

typedef _imp::size_type size_type;

typedef _imp::difference_type difference_type;

typedef _imp::reference reference;

typedef _imp::const_reference const_reference;

typedef _imp::iterator iterator;

typedef _imp::const_iterator const_iterator;

};

所以,還是建議大家,在使用迭代器的時候,如果確定唯讀,直接使用const_iterator,最為保險。

STL 序列容器和關聯容器erase的用法

之前在 中使用map erase函式時,誤搬了vector erase的用法,導致server down掉了,好在在測試環境就及時發現了問題,在上線前進行了補救 以下總結一下map erase的正確用法。首先看一下在迴圈中使用vector erase時我習慣的用法 for vector iterat...

STL序列容器

序列容器 邏輯上有序 但是實際上其位址不一定是連續的.序列容器包括 vector,list,deque,queue,priority queue,stack.我們下面對每乙個容器進行分析.vector容器 大家對vector 一定非常熟悉了 當記憶體不足時候,會對 vector 進行擴容 擴容的方式...

初識STL和容器

stl概念 stl是 c 標準庫的最重要的組成部分,stl 標準模板庫 不僅是乙個可復用的元件庫,而且是乙個包羅演算法和資料結構的軟體框架。stl的六大元件 1.容器 各種資料結構 vector list map set 等 2.迭代器 扮演容器和演算法的膠合劑 3.空間配置器 負責記憶體空間的分配...