《STL原始碼剖析》學習 六大元件

2021-06-20 06:45:34 字數 3503 閱讀 7465

stl 提供了六大元件,分別為:容器、演算法、迭代器、仿函式、介面卡和配置器。

容器通過配置器取得資料儲存空間,演算法通過迭代器訪問容器的內容,仿函式可以協助演算法完成不同的策略,配接器可以修飾或者巢狀仿函式。

下面分別簡單介紹:

1.

容器(container)--  各種資料結構

根據資料排列方式分為序列式和關聯式:

1.1

序列式容器

(1)vector:與c++提供的靜態空間array相比,vector是動態空間。連續空間,支援隨機訪問,迭代器是普通指標。動態增加大小,不是在原空間後面續接新空間,而是以原來兩倍的大小另外開闢空間,然後將原來內容拷貝過來,再在之後新增新元素,釋放空間,乙個「配置新空間,資料移動,釋放舊空間」的過程,因此插入元素不一定是常數時間。當配置新空間後,原來迭代器失效。vector不適用於插入刪除頻繁或者資料量很大的運算,會不停的開闢新空間,釋放空間。

單項開口,只能一端插入刪除元素。

(2)list:雙向鍊錶,不支援隨機訪問,非連續空間,對於任何位置插入或者移除元素都是常數時間。當插入或者刪除元素時,除此元素外迭代器不失效。

雙向開口,前後端都可以插入刪除元素。

提供transfer遷移操作,可以將連續範圍的元素遷移到某個特定位置之前,這是節點之間的移動;

提供splice接合操作,將某連續範圍的元素從乙個list移動到另乙個list的某個定點;

還有merge、reverse和sort操作。

(3)deque :連續線性空間,隨機訪問,雙向開口,雙端插入刪除,允許常數時間內對頭端進行元素的插入刪除。動態地以分段連續空間組合而成,因而沒有預留空間,隨時可以增加一段新空間並連線起來。deque的隨機訪問的代價很大:具有map作為主控,map是一小塊連續空間,其中每個元素指向另一端較大的連續空間(緩衝區);具有複雜的迭代器架構,維護兩個迭代器,start和finish,分別指向緩衝區的第乙個元素和最後緩衝區的最後乙個元素。當插入刪除元素時還包括map的分配更新,緩衝區的分配,迭代器的更新。

(4)stack :一種配接器,底層是deque,通過改變介面,來實現「後進先出」,不允許遍歷,沒有迭代器。

(5)queue :跟stack一樣是一種配接器,底層是deque,先進先出,不允許遍歷,沒有迭代器。

(6)heap:不屬於stl,有大堆和小堆之分,根據完全二叉樹堆排序演算法來保持乙個大堆或者小堆,從而可以每次取得優先權最高的的元素。heap所有元素都必須遵循特別的排序規則,不提供遍歷功能,沒有迭代器。

(7)priority_queue :也是一種配接器,底層是vector,再加上heap排序規則,修改介面,實現自動排序,權值高的在前,只能取走頂端元素,沒有迭代器。

(8)slist:和list類似,只是是單向鍊錶,只有forward iterator,處於效率的考慮,針對此提供了insert_after()和erase_after()。只提供pop_front(),元素次序和插入次序相反。

1.2

關聯式容器:

(1)rb-tree:即紅黑樹,stl不公開,紅黑樹是一種平衡二叉樹,置於紅黑樹的計算過程不做介紹,可參考《演算法導論》13章紅黑樹。這種結構對於資料搜尋效率很高,時間複雜度o(lgn)。

(2)set :根據元素鍵值(也是實值)自動排序,不允許鍵值重複,底層是紅黑樹。

(3)map :根據元素鍵值(第一元素)自動排序,不允許鍵值重複,底層是紅黑樹。

(4)multiset: 與set相同,只是允許鍵值重複。

(5)hashtable: 使用對映的方式將元素對映為大小可接受的索引。解決碰撞簡單的有線性探測,但是容易造成主集團;引出二次探測,可能引發次集團;還有一種方法開鏈,在每個**元素中維護乙個list,sgi stl中採用這種方法。

(6)hash_set:類似於set ,底層機制為hashtable,因為hashtable沒有排序,hash_set 沒有自動排序。

(7)hash_map:類似於map,只是底層機制為hashtable,同樣沒有自動排序。

(8)hash_multiset:類似於multiset,允許鍵值重複,沒有排序。

(9)hash_multimap:類似於multimap,底層機制為hashtable,允許鍵值重複,沒有排序。

2.

演算法(alogrithm)-- 各種演算法

這裡不做具體介紹,都是高效的演算法,需要自己研究。

3.

迭代器(iterator)-- 容器和演算法之間的膠合劑,所有容器都有自己專屬的迭代器。

(1)注意迭代器實現中traits程式設計手法的實現。詳細可見traits

(2)迭代器有五種型別:input、output、forward、bidirectional和random iterator。

4.

仿函式(functor)-- 類似函式的東西,作為演算法的一種策略。

具體見可能令你困惑的c++語法

中最後的仿函式。

5.

配接器 (adapter)-- 用來修飾容器、仿函式或者迭代器介面的東西,使原本不能在一起工作的能工作在一起。

在《設計模式》一書中有此設計模式,定義為:將乙個class的介面轉換為另乙個class的介面,使原本因介面不相容而不能合作的classes,可以一起執行。

stl中的配接器有:container、iterator和functor。containeradapters 有stack和queue,底層都是deque;iterator adapters有insert 、reverse 和stream;function adapters有對返回值進行否定的not1和not2、對引數進行繫結的bind1st和bind2nd、用於函式合成的compose1和compose2、用於函式指標ptr_fun、用於成員函式指標mem_fun和mem_fun_ref。

6.

配置器 (allocator)-- 負責空間的配置和管理

(1)容器預設的配置器為alloc,而非allocator。

(2)stl 將記憶體空間的配置/釋放和物件內容的構造/析構分開,由不同操作負責。記憶體配置操作由alloc:;alllocate()負責,記憶體釋放由alloc::deallocate()負責;物件構造由::construct()負責,物件析構由::destroy()負責。

destroy()有兩個版本,第乙個版本直接呼叫物件的析構函式;第二個版本,如果物件的析構是無關痛癢的(其__type_traits是true),則什麼也不做,否則,呼叫第乙個版本。

(3)記憶體空間採用雙層級配置器。第一級使用malloc()和free(),第二級則視不同的情況採取不同的策略,當配置區域塊超過128bytes時,呼叫第一級配置器;當配置區域小於128byte時,採用memory pool整理方式。因為在小額區太多時,配置時負擔也重,所以在小區域時用的策略也多。

(4)二級配置器,主動將小額區塊的記憶體需求上調至8的倍數,並維護16個freelists,各自管理大小分別為8、16、24、32…128bytes的小額區塊。

STL 原始碼分析六大元件 allocator

1.allocator 基本介紹 分配器 allocator 是c 標準庫的乙個元件,主要用來處理所有給定容器 vector,list,map等 記憶體的分配和釋放。c 標準庫提供了預設使用的通用分配器std allocator,但是,也可以由程式設計師自己提供自定義分配器。2.allocator ...

STL原始碼解析1 六大元件關係

一.stl六大元件介紹 stl就是 容器類 演算法實現 迭代器 配接器 仿函式 配置器 容器通過配置器取得資料儲存空間,演算法通過迭代器訪問容器內容,仿函式可以協助演算法完成不同的策略變化,配接器可以修飾或套界仿函式 1.容器 stl容器包含兩種 序列式容器主要有vector list deque,...

STL六大元件

stl提供六大元件,彼此可以組合套用。1 容器 containers 各種資料結構。如vector,list,deque,set,map,用來存放資料。容器又可以分為順序容器和關聯容器.順序容器 vector,list,deque,stack,queue,heap,priority queue,sl...