目錄
上一小節,我們講解了vector的使用,也大概了解了其建立物件,增刪改查資料等操作.那麼今天,我們就來大致實現一下吧.
在標準c++中,vector同樣是乙個模板,並且其底層實現用的是三個指標,然後利用這三個指標相互加減,達到儲存效果.
而vector和string類似,本質是都是乙個順序表.
template
class vector
private:
t* _start; //順序表的頭
t* _finish; //順序表有效長度位置
t* _end_of_storage; //順序表末尾
};上一章節已經講解,建構函式比較多,這裡只是為了簡單實現,所以博主就實現乙個最簡單的建構函式,即無參構造.
vector():_start(nullptr),_finish(nullptr),_end_of_storage(nullptr) {}
想要獲取size,該怎麼實現呢?我們在定義初始結構的時候,已經知道其底層是利用的三個指標,所以size等於_finish - _start.
size_t size() const //加const是保證const物件也可以用
同樣的道理,capacity就應是_end_of_storage - _start;
size_t capacity() //加const是保證const物件也可以用
我們在後面會實現乙個介面,叫做push_back(),它的作用是把資料放進vector,但如果空間不足了呢?這就需要我們的增容函式reserve了.
其引數是無符號整型n,代表要開n個空間
void reserve(size_t n)
_start = tmp; //移交空間
_finish = _start + sz; //更新_finish
_end_of_storage = _start + n; //更新_end_of_storage}}
這個想必大家現在已經比較習慣了吧?他有兩個引數,會分情況討論是否大於size()而進行引數賦值.
void resize(size_t n,const t& val = t())
iterator end() //普通介面
const_iterator begin() const
const_iterator end() const //const介面
該介面的實現操作一般是先檢查容量是否充足,然後把資料放進去,最後size大小加一.
void push_back(const t& val)
*_finish = val;
_finish++;
}實現該介面的操作一般是先檢查是否還存在資料,然後size大小減一
void pop_back()
同樣的道理,一般先檢查容量是否充足,如果不夠,需要警惕迭代器失效問題,然後移動該位置及以後的所有資料,最後插入資料.
官方文件定義其返回值為新插入資料的位置
iterator insert(iterator pos,const t& val)
iterator cur = end();
while(cur > pos)
*pos = val;
_finish++;
return pos;
}該介面的操作一般是從pos後位置開始,所有資料前挪一單位.但是在挪之前,需要檢查是否還存在資料
官方文件定義其返回值為刪除資料的下一位置
iterator erase(iterator pos)
--_finish;
return pos;
}vector(const vector& v):_start(nullptr), _finish(nullptr), _end_of_storage(nullp程式設計客棧tr)
}上面我們實現了迭代器,但是vector還支援索引取值,博主這裡便實現兩個過載吧
t& operator(size_t i)
const t& operator(size_t i) const
vector& operator=(vector v) //注意哦~,我這裡故意寫的傳值引數,而不是引用,是為了下面進行交換
在實現了上面的一系列操作以後,有沒有覺得我們已經大功告成了?其實這裡還隱藏著乙個小小bug!.為什麼呢?看下面'
int main()
初一看,好像並沒有什麼錯誤哎?但是一執行就會發現,當插入第5個元素的時候,就報錯了.這是什麼原因呢?
除錯發現,問題出在了reserve上面,因為push_back之前,會檢查容量,那麼我們現在重新瞅瞅 reserve存在什麼問題呢?
void reserve(size_t n)
_start = tmp; //移交空間
_finish = _start + sz; //更新_finish
_end_of_storage = _start + n; //更新_end_of_storage}}
大家有發現什麼問題了嗎?
沒錯,問題出現在memcpy上面,當容量不足,reserve就會增加容量,然後把原來空間的內容值拷貝到新空間.
但是原來空間的內容也就只有三個指標呀,拷貝過去後,新空間和源空間都指向了同一塊空間,而我們又會釋放原空間.
所以,當繼續尾插第5個元素時候,就報錯了,因為空間已經不存在了!!!,被釋放了.
那怎麼解決呢?這裡便只能用迴圈,把string值賦給新空間了.
void reserve(size_t n)
delete _start;
}_start = tmp;
_finish = _start + sz;
_endofstorage = _start + n;
}本文標題: c++入門之vector的底層實現詳解
本文位址:
C語言資料結構之vector底層實現機制解析
目錄 通過分析 vector 容器的源 不難發現,它就是使用 3 個迭代器 可以理解成指標 來表示的 其中statrt指向vector 容器物件的起始位元組位置 finish指向當前最後乙個元素的末尾位元組 end of指向整個 vector 容器所占用記憶體空間的末尾位元組。如圖 演示了以上這 3...
c 之vector容器入門
對於c 的vector容器的函式應用 include include include using namespace std intmain cout cout 迭代器形式結果 for it vt.begin it vt.end it cout cout vt元素個數是 size函式 插入元素函式 ...
STL中vector的底層解析及簡易實現
vector是一種動態增長的陣列,當原始容量被用盡後,在別的地方進行擴充,大小為原來的2倍,然後將內容拷貝過去 成長過程如下圖所示 下面是vector的關鍵源 templateclass vector iterator end size type size const size type capac...