STL 源碼剖析:deque 的實現原理

雖然 deque 從表面上來說,它採用連續的空間,並且支持隨機訪問,即其迭代器爲 random_access_iterators 類型。而且相比 vector,它還支持 push_front()。

//
//

​ 但是實際上,deque 只是邏輯上的連續空間。它需要維護一個特殊的東西,叫做 deque 的中控器。該中控器主要由一個二級指針和一個 size 構成,(即可以理解爲,該中控器是一個一級指針數組,下面我們用這個詞來講解)。

//
//

​ 中控器是一個指針數組,數組中的每一個指針指向一個緩衝區 (即一塊連續空間)。

​ 初始時,會首先配置出這個中控器的空間,然後配置出需要的若干個緩衝區的空間,將這若干個緩衝區放在中控器的中間部分(使得頭尾兩端可擴充的緩衝區數量一樣大)。

注意:只有配置了的纔有空間,而且配置僅僅代表分配空間,該空間時原始的,並沒有初始化。即,中控器初始時,裏面的每個值都還沒有構造,緩衝區也是同理。我們會在需要的時候進行構造。

//
//

​ 當然,這就還會涉及到中控器空間不足的問題。(後述)

//
//

​ deque 的迭代器中包含 4 個重要部分,該迭代器指向的緩衝區 (即該迭代器指向中控器的哪一個位置),該緩衝區的首指針,尾指針 以及 當前的指針位置 cur。即,對於首迭代器來說,我們每一次構造都是先 – cur,然後在 cur 這個位置上進行構造;對於尾迭代器,我們在 cur 位置上進行構造,然後 ++ cur。(這裏不包括緩衝區用盡的情況)

你可以將迭代器理解爲一個指針,指向中控器的某一個位置,但這個指針同時還包含一些額外的信息。

//
//

​ 那麼中控器是如何維護的呢。其實就是兩個迭代器,首和尾迭代器。可以把首尾迭代器想象成兩個指針,指向中控器中目前使用的首位置和尾位置。所以當緩衝區用盡時,假設是首迭代器的緩衝區用盡,我們就會配置一個新的緩衝區,然後將緩衝區的首指針放在中控器中的首迭代器的前一個位置,然後更新首迭代器;如尾迭代器的緩衝區用盡,我們就會配置一個新的緩衝區,然後將緩衝區的首指針放在中控器中的尾迭代器的後一個位置,然後更新尾迭代器。(當然,這裏未考慮中控器空間不足的情況)。

//
//

​ 而邏輯上,deque 的迭代器是 random_access_iterators,所以我們還需要爲它重載 ++,+=, --, -=, -, +, <, >,[] 等運算符。即滿足 random_access_iterators 的所有操作。

//
//

​ 當中控器空間不足時,會考慮到能否通過在中控器中移動 [start, finish+ 1) 使得 start 和 finish 兩端有多餘空間(足以滿足需求的新增數量),而決定是否真正的配置新的中控器空間。

​ 若配置新的空間,就需要將原來的內容拷貝到新空間中,然後釋放舊空間。

//
//
實現還是有些複雜,但原理是這樣。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章