首先是vector的定義
template classvector
;
讓我們先來看看vector中的一些別名
public: typedef t value_type;
typedef t*pointer;
typedef t&reference;
typedef
const t&const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef
const t*const_iterator;
typedef reverse_iterator
const_reverse_iterator;
typedef t*iterator;
typedef reverse_iterator
reverse_iterator;
由上可見,正如
所說,vector的迭代器是由原生的指標來實現的。
下面是其內部的成員變數
protected: typedef vector
self;
typedef allocator
alloc;
iterator start;
iterator finish;
iterator end_of_element;
end_of_element:指向已申請記憶體塊的結束位置(finish總是小於或等於end_of_element)
在stl中從begin到end總是以乙個前閉後開的形式來表示的,形如[begin,end),這樣做的好處是可以使**寫的更簡潔:
template iterator find(iterator first, iterator last,const t&value)
下面來看看vector中最基本的建構函式和析構函式
vector() : start(0), finish(0), end_of_element(0)
~vector()
這裡將其中的3個成員變數都填充為0。
如所說,在stl中是將記憶體分配與物件初始化分開的,同樣物件析構與記憶體釋放也是被分開的。
然後是其begin和end方法,用來獲取第乙個元素和最後乙個元素的後乙個元素的迭代器。
inline iterator begin()inline const_iterator begin()
const
inline iterator end()
inline const_iterator end()
const
front和back分別被用來獲取第乙個元素和最後乙個元素
inline reference front()inline const_reference front()
const
inline reference back()
inline const_reference back()
const
empty、size、capacity分別被用來判別容器是否為空、容器內元素的個數和容器的大小
inline bool empty()constinline
const size_type size()const
inline
const size_type capacity()const
由於在vector的頭部插入元素會使所有元素後移,應此它被設計為單向的,只能由尾部插入或移除資料
void push_back(const t&x)else
}inline
void
pop_back()
當然從頭部移除資料也並非不可以,可以使用erase方法來移除頭部的資料,erase方法將會在後面的部分作出說明。
我們先來看一下insert_aux這個方法,在插入元素時幾乎都使用到了這個方法。
void insert_aux(const iterator position, const t&x)else
}
在容器還有足夠的空間時,首先將從position位置到finish位置的元素整體後移乙個位置,最後將要被插入的元素寫入到原position的位置同時改變finish指標的值。
若空間不足時,首先根據原有空間的大小的一倍來申請記憶體,然後將元素從原有位置的begin到position拷貝到新申請的記憶體中,然後在新申請記憶體的指定位置插入要插入的元素值,最後將餘下的部分也拷貝過來。然後將原有元素析構掉並把記憶體釋放掉。
為何不使用
reallocate?
reallocate的本意並不是在原有記憶體的位置增加或減少記憶體,reallocate首先會試圖在原有的記憶體位置增加或減少記憶體,若失敗則會重新申請一塊新的記憶體並把原有的資料拷貝過去,這種操作本質上等價於重新申請一塊記憶體,應此這裡使用的是allocate而並非reallocate。
然後讓我們來看一下insert和erase方法
inline iterator insert(iterator position, const t&x)else
insert_aux(position, x);
return begin() +pos;
}iterator erase(iterator position)
--finish;
return
position;
}
若是要在最後插入乙個元素且容器的剩餘空間還足夠的話,直接將元素插入到finish的位置,並將finish指標後移一位即可。若容器空間不夠或不是插在最後乙個的位置,則呼叫insert_aux重新分配記憶體或插入。
刪除時首先析構掉原有元素,若被刪元素不是最後乙個元素,則將後面的所有元素拷貝過來,最後將finish指標前移乙個位置。
最後讓我們來看一下其中過載的運算子
self& operator=(const self&x)else
return *this
; }
inline reference
operator
(size_type n)
inline value_type at(size_type n)
由於vector內部用的是原生的指標,應此這些運算子的使用方式和原生指標的並無差異。值得注意的是在做賦值操作時會產生記憶體的重新分配與拷貝操作。
至此,vector的講解已完成,完整的**請到
山寨STL實現之list
在stl中list是以雙向鍊錶的方式來儲存的,應此使用給定的下標值來找到對應的節點所需的時間複雜度為o n 相比vector直接使用原生指標會慢一些。因為是雙向鍊錶的關係,那麼必然有一種結構來表示鍊錶中的節點。template struct list node list node const t x...
山寨STL實現之allocator
作為乙個山寨的stl,那麼不得不提的是其中的allocator 空間配置器 顧名思義,它是負責空間分配用的,下面 十分簡單,僅對c函式malloc和free進行了薄薄的一層封裝,同時給定了自定義函式free handler用於在空間分配時候由於記憶體被佔滿了而導致的分配失敗。這裡值得注意的是 這個釋...
山寨STL實現之記憶體池
記憶體池的作用 減少記憶體碎片,提高效能。首先不得不提的是win32和x64中對於指標的長度是不同的,在win32中乙個指標佔4位元組,而在x64中乙個指標佔8位元組。也正是不清楚這一點,當我在x64中將指標作為4位元組修改造成其他資料異常。首先我們先來定義三個巨集 define align siz...