1. 程式人生 > >STL及一些容器底層實現機制

STL及一些容器底層實現機制

失效 list容器 容量 較高的 浪費 復制 處理 跳轉 strong

1、vector容器

vector的數據安排以及操作方式,與數組類似。倆這唯一的區別就是空間的運用靈活性。數組是靜態空間,一旦配置了就不能改變,vector是動態數組。在堆上分配內存。vector是動態空間,隨著元素的加入,它的內部機制會自動擴充空間容納新的元素當前大小實惠再分配內存,這個大大影響了vector的效率。因此,vector的運用對於內存的合理利用與運用的靈活性有很大的幫助,我們再也不必因為空間不足而已開始要求一個大的數組。

vector動態的增加大小,並不是在元空間之後持續新空間,二十余原大小的兩倍另外配置一塊較大的空間,然後將原內容拷貝過來,然後才開始在原來的內容之後構造新元素,並釋放元空間。因此,對vector的任何操作,一旦因其空間重新配置,同時執行原vector的所有叠代器都失效了。

對最後的元素操作最快,此時一般不需要移動內存對中間的開始處進行添加刪除元素操作需要移動內存。如果你的元素使結構或石磊,那麽移動的同時還會進行構造和析構的操作,所以性能不高。訪問方面,對任何元素的訪問都是O(1)也就是常數時間。

總結:vector常用來保存需要經常進行隨機訪問的內容,並且不需要對中間元素進行添加刪除操作。

2、list容器:每次插入或者刪除一個元素,就配置或者釋放一個元素空間,元素也是在堆中。因此,list對於空間的運用有絕對的精準,一點也不浪費。而且,對於任何位置的元素的插入或元素移除,永遠是常數時間。STL中的list底層是一個雙向鏈表,而且是一個環裝雙向鏈表。這個特點使得他的隨機存取變得非常沒有效率,因此,他沒有提供[]操作符的重載。

總結:如果添加或者刪除大對象的話,使用list;要保存的對象不打,構造與析構操作不復雜可以使用vector代替;

list<指針>完全是性能最低的做法,這種情況還是使用vector<指針>號,因為指針沒有構造與析構,也不占用很大內存。

3、deque容器

是一種雙向開口的連續線性空間,元素也是在堆中。所謂雙向開口,意思是可以在對威力A段分別作元素的插入和刪除。deque和vector最大差異,一是:deque允許常數時間內對起頭端進行元素的插入或移除操作,二在於、deque沒有所謂容量觀念,因為他是動態地一分段連續空間組合而成,隨時可以增加以短信的空間並連接在一起。

deque 是由一段一段的定量連續空間構成。一旦有必要在 deque 的前端或尾端增加新空間,便配置一段定量連續空間,串接在整個 deque 的頭端或尾端。deque 的最大任務,便是在這些分段的定量連續空間上,維護其整體連續的假象,並提供隨機存取的接口。避開了“重新配置,復制,釋放”的輪回,代價則是復雜的叠代器架構。因為有分段連續線性空間,就必須有中央控制器,而為了維持整體連續的假象,數據結構的設計及叠代器前進後退等操作都頗為繁瑣。

  deque使用一塊所謂的map作為主控。這裏的map是一小塊內存空間,其中每個元素都是指針,指向領一塊兒線性空間稱為緩沖區。緩沖區才是deque的存儲空間主體。

支持[]操作符,也就是支持隨即存取,可以在前面快速地添加刪除元素,或是在後面快速地添加刪除元素,然後還可以有比較高的隨機訪問速度和vector 的效率相差無幾。deque 支持在兩端的操作:push_back,push_front,pop_back,pop_front等,並且在兩端操作上與 list 的效率也差不多。
在標準庫中 vector 和 deque 提供幾乎相同的接口,在結構上區別主要在於在組織內存上不一樣,deque 是按頁或塊來分配存儲器的,每頁包含固定數目的元素;相反 vector 分配一段連續的內存,vector 只是在序列的尾段插入元素時才有效率,而 deque 的分頁組織方式即使在容器的前端也可以提供常數時間的 insert 和 erase 操作,而且在體積增長方面也比 vector 更具有效率。

總結:vector是可以快速的最後添加刪除元素,但是只能快速的訪問任何元素;list是可以快速的額在所有地方添加和刪除元素,但是只能快速的訪問最開始和最後的元素;deque在開始和最後天元素都一樣快,並提供了隨機訪問方法,像vector一樣使用[]訪問任何元素,但是隨機訪問速度比不上vector快,因為他要內部處理跳轉。deque也有保留空間。另外,有與deque不要求連續空間,所以可以保存的元素幣vector更大,這點也要註意一下。還有就是後面添加元素時候都不需要啟動其他快的元素,所以性能也高。

因此在實際使用時,如何選擇這三個容器中哪一個,應根據你的需要而定,一般應遵循下面的原則:

1、如果你需要高效的隨即存取,而不在乎插入和刪除的效率,使用 vector;
2、如果你需要大量的插入和刪除,而不關心隨即存取,則應使用 list;

3、如果你需要隨即存取,而且關心兩端數據的插入和刪除,則應使用deque。

4、stack:是一種先進後出的存儲結構。他只有一個出口,stack允許新增元素,一處元素,取得頂端元素,但是除了最頂端之外沒有任何其他方法可以存取stack的其他元素,stack不允許遍歷行為。

以某種容器( 一般用 list 或 deque 實現,封閉頭部即可,不用 vector 的原因應該是容量大小有限制,擴容耗時)作為底部結構,將其接口改變,使之符合“先進後出”的特性,形成一個 stack,是很容易做到的。deque 是雙向開口的數據結構,若以 deque 為底部結構並封閉其頭端開口,便輕而易舉地形成了一個stack。因此,SGI STL 便以 deque 作為缺省情況下的 stack 底部結構,由於 stack 系以底部容器完成其所有工作,而具有這種“修改某物接口,形成另一種風貌”之性質者,稱為 adapter(配接器),因此,STL stack 往往不被歸類為 container(容器),而被歸類為 container adapter。

5、queue:是一種先進先出的存儲結構。有倆個出口,queue允許新增元素,移除元素,從最低端加入元素,取得最頂端元素。但除了最低端可以加入,最頂端可以取出外,沒有人其他方法可以存取queue的其他元素。

6、map和multimap:map的特性是:所有元素都會根據元素的鍵值自動被排序。map的所有元素都是pair,同時擁有實值value和減值key。pair的第一元素被視為鍵值,第二元素被視為實值。map不允許倆各元素擁有相同的鍵值。由於紅黑樹是一種平衡二叉搜索樹,自動排序的效果很不錯,所以標準庫STLmap就是以紅黑樹為的層級制。又由於map所開放的各種操作接口,紅黑樹也都提供了,所以幾乎所有map的操作行為,都是紅黑樹的操作行為。

multimap的特定以及用法與map完全相同,唯一的差別在於他允許鍵值重復,因此它的插入操作采用的是它的底層機制的insert_equal()而非insert_unique。

STL及一些容器底層實現機制