STL之deque原始碼剖析

2021-06-21 09:17:42 字數 4339 閱讀 7699

deque是一種那個雙向開口的連續線性空間,其頭尾端做元素的插入和刪除效率比vector效率高很多。deque和vector的最大差異,一在於deque允許常數時間內對頭尾端進行元素插入或移除操作,二在於deque沒有所謂容量概念,因為它是動態地分段連續空間組合而成,隨時可以增加一段新的空間並鏈結起來。

deque提供的迭代器也是randomaccess iterator,但它的迭代器並不是普通指標。對deque進行排序操作,為了最高效率,可將deque先完整的複製到乙個vector身上,將vector排序後(利用stl的sort演算法),在複製回deque。

deque是由一段一段的定量連續空間構成。一旦有必要在deque的前端或尾端增加新空間,便配置一段定量連續空間,串接在整個deque的頭端或尾端。deque的最大任務,便是在這些分段的定量連續空間上,維護其整體連續的假象,並提供隨機訪問的介面。

deque採用一塊所謂map(不是stl中的map)作為主控。這裡所謂的map是一小塊連續空間,其中每個元素(此處成為乙個節點,node)都是指標,指向另一段(較大)連續線性空間,稱為緩衝區。緩衝區才是deque的儲存空間主體。sgi stl允許我們指定緩衝區大小,預設值0表示將使用512bytes緩衝區。

typedef value_type*pointer;

//元素指標的指標

typedef pointer* map_pointer;

map_pointer map;        //指向map,map是連續空間,其內的每個元素都是乙個指標,指向

//一塊緩衝區

size_typemap_size;      //map內可容納多少指標

deque是分段連續空間。維持其」整體連續」假象的任務,落在了operator++和operator--上。

deque迭代器維護四個指標,乙個指向緩衝區現行元素,乙個指向緩衝區的頭,乙個指向緩衝區的尾,還有乙個指向對於管控中心中的節點。

下面是迭代器的部分源**:

template struct __deque_iterator 

#endif

//未繼承std::iterator,所以必須自行撰寫五個必要的迭代器相應型別

typedef random_access_iterator_tag iterator_category; // (1)

typedef t value_type; // (2)

typedef ptr pointer; // (3)

typedef ref reference; // (4)

typedef size_t size_type;

typedef ptrdiff_t difference_type; // (5)

typedef t** map_pointer;

typedef __deque_iterator self;

// 保持與容器的聯結

t* cur; // 此迭代器所指的緩衝區中的現行元素

t* first; // 此迭代器所指的緩衝區的頭

t* last; // 此迭代器所指緩衝區的位(含備用空間)

map_pointer node; //執行管控中心

__deque_iterator(t* x, map_pointer y)

: cur(x), first(*y), last(*y + buffer_size()), node(y) {}

__deque_iterator() : cur(0), first(0), last(0), node(0) {}

__deque_iterator(const iterator& x)

: cur(x.cur), first(x.first), last(x.last), node(x.node) {}

// 以下各個過載運運算元是__deque_iterator<>成功運作的關鍵

reference operator*() const

#ifndef __sgi_stl_no_arrow_operator

pointer operator->() const

#endif /* __sgi_stl_no_arrow_operator */

difference_type operator-(const self& x) const

// postfix forms of increment and decrement operators.

self& operator++()

return *this;

} self operator++(int)

self& operator--()

--cur; // 切換至前一元素

return *this;

} self operator--(int)

self& operator+=(difference_type n)

return *this;

} // stand-alone op.

self operator+(difference_type n) const

self& operator-=(difference_type n)

// 以上利用operator+= 來完成 operator-=

// stand-alone op.

self operator-(difference_type n) const

reference operator(difference_type n) const

// 以上呼叫operator*, operator+

bool operator==(const self& x) const

bool operator!=(const self& x) const

bool operator<(const self& x) const

void set_node(map_pointer new_node)

};

deque的構造、記憶體管理,以及元素操作:

dequeue自行定義了兩個專屬的空間配置器。乙個用於配置元素空間,另乙個用於配置map空間大小。首先會配置map空間,使map空間最**區段得到利用,最**區段的每個節點都對於乙個即將分配的緩衝區。然後配置緩衝區,所以緩衝區加起來就是deque的可用空間(最後乙個緩衝區可能有一些餘裕)。然後為deque內的兩個迭代器start和end設定正確內容。

push_back()實現:當尾端有兩個以上的元素備用空間,直接在備用空間上構造元素,然後更改迭代器finish的狀態。當緩衝區只剩下乙個元素備用空間,會先配置一整塊新的緩衝區,再設妥新元素內容,然後更改迭代器finish的狀態。

push_front()實現:當第一緩衝區尚有備用空間,直接在備用空間上構造元素,調整第一緩衝區的使用狀態。當第一緩衝區已無備用空間,配置乙個新緩衝區,調整start狀態,設妥新元素內容。

當執行push_back()時,map尾端的節點備用空間不足或執行push_front()時,map前端的節點備用空間不足就重新配置一塊更大的空間(new_map_size = map_size + max(map_size,nodes_to_add)+2 )給新map使用,然後把元map內容拷貝過來,釋放原來map,設定新map的起始位址和大小。

pop_back()實現:當緩衝區有乙個以上元素,調整finish狀態,析構最後乙個元素。當最後緩衝區沒有任何元素時,則將最後乙個緩衝區釋放,調整finish狀態,使指向上乙個緩衝區的最後乙個元素,將該元素析構。

pop_front()實現:第乙個緩衝區有兩個以上元素,將第乙個元素析構,調整指標。當第乙個緩衝區只有乙個元素,將第乙個緩衝區的元素析構,釋放第乙個緩衝區,調整start狀態,使指向下乙個緩衝區的第乙個元素。

clare()實現:用來清除整個deque,注意deque的最初狀態保有乙個緩衝區,因此clear()完成之後恢復初始狀態,也需要保留乙個緩衝區。首先將除了頭尾以外的每乙個緩衝區中的元素析構,然後釋放記憶體。再將頭尾緩衝區元素析構,釋放尾部緩衝區記憶體,頭緩衝區保留調整finish和start狀態。

erase()實現:用來清除乙個前閉後開區間內的所有元素。如果是清除整個區間,直接掉頭clear()。為提高效率,如果清除區間前方元素比較少,那就向後移動前方元素(覆蓋清除區間),將冗餘的元素析構。如果後方元素比較少,那就向前移動後方元素(覆蓋清除區間),將冗餘的元素析構。

insert()實現:允許在某個點之前插入乙個元素。如果插入點是最前端,交給push_front去做,如果插入點是最尾端,交給push_back去做。否則如果插入點之前的元素個數比較少,在最前端加入與第乙個元素同值的元素,然後使舊的第乙個點到插入點之前的元素向前移動,最後在插入點上設定新值。否則,在最尾端加入與最後元素同值的元素,然後進行元素移動,最後在插入點出設定新值。

STL原始碼剖析 deque!!!

面試網易的時候特麼問我deque,從來沒用過啊 委屈臉 deque和vector的區別 deque允許於常數時間內對頭端進行元素的插入和移除操作。deque沒有capacity觀念。deque沒有像vector那樣 因舊空間不足而重新配置一塊更大的空間,然後複製元素,再釋放舊空間 如果想為deque...

STL原始碼剖析 序列式容器之deque

deque概述 deque是一種雙開口的連續線性空間,可以在頭尾兩端分別做元素的插入和刪除操作 deque沒有容量的概念,它是動態地以分段連續空間組合而成,隨時可以增加一段新的空間並鏈結起來 deque的中控器 deque由一段一段的定量連續空間構成 一旦有必要在deque前端或尾端增加新空間,便配...

STL原始碼剖析 deque的中控器

deque是連續空間 至少邏輯上看來如此 連續線性空間總令我們聯想到 array 或vector array 無法成長,vector 雖可成長,卻只能向尾端成長,而且其所謂成長原是個假象,事實上是 1 另覓更大空間 2 將原資料複製過去 3 釋放原空間三部曲。如果不是 vector 每次配置新空間時...