關於STL中vector的記憶體管理與簡單代碼實現

來源:互聯網
上載者:User

vector 的內部實現其實就是一塊連續記憶體,它和傳統的array不同的是支援擴容,不用考慮越界。vector的迭代器就是最簡單的指向容器內類型的指標。其內部有三個指標,start(指向資料存放區區的首地址),finish(已使用的資料區的尾端),end_of_storage(指向容量尾端,容量一般富餘),當遇到滿載的情況,finish指標和 end_of_storage 指標相等,也就是容量用完的時候,如果繼續插入元素,就會擴容。

需要擴容的時候,空間適配器就會從新尋找一塊更大的記憶體空間(因為vector內部是一塊連續的記憶體),然後start指向新記憶體首地址,未經處理資料複製,新資料插入,同時更新finish以及end_of_storage即可。擴容的規模一般是原始容量的兩倍。

下面的代碼參照 侯捷《STL源碼剖析》第四章。意在瞭解vector的記憶體管理以及各個介面的實現。出於簡單考慮,部分介面沒有按照標準做,空間適配器的部分是我自己手動實現的,也沒有再做成公用介面,而是直接加在函數實現裡面了,可能比較粗糙。

#include<iostream>using namespace std;template <class T>class MyVector{public:typedef T * iterator;typedef T * pointer;typedef T & reference;MyVector():start(0),finish(0),end_of_storage(0){}MyVector(int n,const reference val)//申請n單位空間,並用val初始化{start = new T[n];finish = start;end_of_storage = start + n;while(n--) { *finish++=val; }}MyVector(int n)//申請n單位空間,初始化為0{start = new T[n];finish = start;end_of_storage = start + n;while(n--) { *finish++=0; }}~MyVector(){iterator i;for(i=start;i<end_of_storage;i++) i->~T();}iterator begin() const { return start; }iterator end() const { return finish; }//注意size的定義,傳回值是end - begin,也就是說,finish指向的是最後一個元素後面的一個地址int size() const { return int(end()-begin()); }//void resize(int new_size,const reference x);//重新定義空間大小,而且完成初始化,finish指標在空間尾端//void resize(int new_size);//void reserve(int new_size);//重新定義空間大小,但是不改變finish指標int capacity() const { return end_of_storage-begin(); }bool empty() const { return begin() == end(); }reference operator[](int n) { return *(begin()+n); }reference front() { return *begin(); }reference back() { return *(end()-1); }void push_back(const reference x){if(finish != end_of_storage)//未滿載{*finish = x;finish++;}else insert(end(),1,x);//滿載,需要重新分配空間,並完成已有成員的搬移}void pop_back()//刪除尾端元素{finish--;finish->~T();}void erase(iterator first,iterator last)//清除[first,last)的所有元素{int j = end()-last;for(int i=0;i<j;i++){*(first+i) = *(last+i);}while(end()>first+j){pop_back();}}void erase(iterator position)//清除指定位置元素{erase(position,position+1);}void clear(){//清空vectorerase(begin(),end());}void insert(iterator position,int n,const reference x);//從position開始插入n個元素,每個元素的初始值為x//void insert_aux(iterator position, const reference x);//重新分配空間,並完成已有成員的搬移private:iterator start;iterator finish;iterator end_of_storage;};template <class T>void MyVector<T>::insert(iterator position,int n,const reference x)//從position開始插入n個元素,每個元素的初始值為x{/*STL的vector<class type>::insert(type * , int , const type &) 作用:在指定位置插入元素,有可能引起擴容當插入導致finish 指標大於 end_ofstorage 時,就需要擴容*/iterator i = start;//old_startiterator new_finish;//不擴容的話指向old_start,擴容的話指向new_startiterator old_start = start,old_finish = finish;bool needToDestory = false;if(finish+n > end_of_storage){needToDestory = true;const int old_size = size();const int len = old_size + n;start = new T[len];new_finish = start;end_of_storage = start + len;}else {new_finish = start;end_of_storage = finish + n;}/*未經處理資料的搬移*/while(i<position) { *new_finish++ = *i++; }/*插入部分的初始化*/while(n--) { *new_finish++ = x; }/*未經處理資料的搬移*/while(i<finish) { *new_finish++ = *i++; }finish = new_finish;/*這裡需要釋放原有空間*/if(needToDestory==true){while(old_start != old_finish){old_start->~T();old_start++;}}}/*template <class T>void MyVector<T>::insert_aux(iterator position,const reference x){insert(position,1,x);//重新分配空間,並完成已有成員的搬移}*/struct Node{Node(){}Node(int a=0,int b=0):x(a),y(b){}int x,y;};int main(){MyVector<Node> test(3);cout <<"size of vector now : "<< test.size() << "\t" <<"capacity of vector now : "<< test.capacity() << endl;for(int i=0;i<3;i++){Node a(i,i*i);test.push_back(a);/*push_back()是從end()端插入,而初始化過的vector的end()是和capacity()相等的,所以會發生擴容,也就是說,我們插入的三個點(0,0),(1,1),(2,4)的位置是在a[3],a[4],a[5]中,而a[0],a[1],a[2]中還是初始化時的值,如果覺得這樣浪費的話,想把點插入到最開始的位置的話,有以下幾種方法:  NODE 1:可以再申請容器的時候,不指定大小(預設為0),那麼後續插入引起擴容,自然就從第一個位置(a[0])開始了  NODE 2:用reserve(N)指定大小,這個函數不會修改finish指標,也就是說,finish指標指向的是begin()端  PS:reserve()介面這裡我沒有實現,留到以後有時間加上吧  NODE 3:用insert()在指定位置插入點,但是這樣會引起擴容  NODE ……歡迎補充 ^_^*/}cout <<"size of vector now : "<< test.size() << "\t" <<"capacity of vector now : "<< test.capacity() << endl;MyVector<Node>::iterator pi;for(pi = test.begin();pi != test.end();pi++){cout << pi->x << " " << pi->y << endl;}/******測試insert()******/test.insert(test.begin(),7,test[5]);//在begin()端插入7個元素,容量變為 size() + 7cout <<"size of vector now : "<< test.size() << "\t" <<"capacity of vector now : "<< test.capacity() << endl;MyVector<Node>::iterator pj;for(pj = test.begin();pj != test.end();pj++){cout << pj->x << " " << pj->y << endl;}return 0;}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.