山寨STL實現之vector

2022-04-28 06:40:40 字數 3544 閱讀 6589

首先是vector的定義

template class

vector

;

讓我們先來看看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()const

inline

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...