STL(Standard Template Library)
咱們使用庫函數很是方便,且很是高效(相對於本身實現來講)。那如此好用的模板庫它的內裏是什麼樣的?它揹着咱們施展了什麼「魔法」呢?我決定一探究竟,相信你也是同樣。我會選用部分重要代碼作分析,用來提高本身,但願後來的你在個人拙見中也能有本身的收穫。ios
vector
數據存儲方式:線性存儲(一塊連續內存),相似array。數組
相比於內置數組(不是array哦)的優點:動態擴容。(其實也不算什麼優點,數組也徹底能夠作,只不過它把擴容過程高效安全地封裝了起來。)安全
相比於array,優點就更大了,array的容量開始就是定死了的,沒法擴容。函數
使用方法測試
1 #include <iostream> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 6 // unique_ptr::get vs unique_ptr::release 7 int main() 8 { 9 //初始化 10 vector<int> vec;//聲明,未初始化 11 vector<int> vec1(2, 5);//2個5 12 vector<int> vec2 = { 1, 2, 3, 4, 5 };//直接初始化
13 //讀取元素 14 cout << "第2個元素: " << vec2[1] << endl; 15 cout << "首元素: " << vec2.front() << endl; 16 cout << "尾元素: " << vec2.back() << endl;
17 //插入元素 18 vec1.insert(vec1.begin(), 999);//para1-插入位置,要迭代器即指針,para2-插入內容 19 vec2.push_back(888);//尾部插入 20 vec2.pop_back();//刪除尾部,相似於stack,因此有時候也能夠把vector當stack用
21 //刪除元素 22 vec2.erase(vec2.end()-1);//參數也是迭代器類型,因此使用insert和erase時,最好用iterator來遍歷
23 //排序 24 sort(vec2.begin(), vec2.end());//給出首位指針 25 sort(vec2.begin(), vec2.begin()+3);//甚至這樣也能夠,由於iterator自己就是類型指針 26 27 //遍歷--下標索引訪問 28 cout << "vec1 : " ; 29 for (int i = 0; i < vec1.size(); ++i) 30 { 31 cout << vec1[i] << " "; 32 } 33 34 //遍歷--迭代器指針訪問 35 cout << "\nvec2 : "; 36 vector<int>::iterator it; 37 for (it=vec2.begin(); it != vec2.end(); ++it) 38 { 39 cout << *it << " "; 40 }
41 //使用指針遍歷vector
auto vec = new vector<int>(10, 8);
for(int i=0; i<vec->size(); i++)
cout << (*vec)[i] << " ";
41 return 0; 42 }
好了,基本的用法就是這樣。spa
底層是怎麼實現的呢?
在STL源碼中,vector類維護有三個迭代器(三個類型指針)start, finish, end_of_storage, 分別表明頭, 尾(實際使用的), vector 存儲尾部(佔用的,一般大於實際使用)。3d
當咱們vector<TYPE>::iterator it;時,it就是TYPE* 類型指針,上述三個迭代器也是如此。指針
庫函數的實現呢?
咱們能夠看出,經過上述的三個指針,幾乎全部的操做均可以進行了。值得一提的是vector重載了[ ],能夠方便存取值。code
須要注意的是,當咱們訪問尾元素時,迭代器可不是*.end(),而是*.end()-1。blog
那麼咱們再來探討一下,有意思的東西。
插入元素時,預設的end_of_storage不夠怎麼辦?怎麼進行擴容。
再看源碼!
整個的流程是:
1.先申請兩倍內存,判斷夠不夠,夠進入2;不然,分配須要的大小;
2.拷貝要插入點以前的內容
3.構造插入元素順次添加到後面
4.接着把以前插入點後面的內容拷貝到新的空間中
5.釋放原來空間
來看一下GCC的vector擴容過程,大概是,不夠就擴充爲原來2倍,擴充爲原來2倍還不夠,則擴充至須要大小。
1 int main() 2 { 3 vector<int> vec; 4 for(int i=0; i<20; i++) 5 { 6 cout << "vector size= " << vec.size() << endl; 7 cout << "vector capacity= " << vec.capacity() << endl; 8 //cout << "vector max_size= " << vec.max_size() << endl; 9 vec.push_back(i); 10 } 11 cout << "最後一次, 插入100個元素 " << endl; 12 vec.insert(vec.begin(), 100, 1); 13 cout << "vector size= " << vec.size() << endl; 14 cout << "vector capacity= " << vec.capacity() << endl; 15 //cout << "vector max_size= " << vec.max_size() << endl; 16 17 return 0; 18 }
可是,vector最大空間是固定的。
我用同一段代碼測試vector的最大空間 ,這裏有一個疑問,要是超過額定最大空間又會怎麼樣?最後有嘗試。
1 int main() 2 { 3 vector<int> vec; 4 for(int i=0; i<20; i++) 5 { 6 cout << "Max_size = " << vec.max_size() << endl; 7 cout << "size = " << vec.size() << endl; 8 vec.push_back(i); 9 cout << "插入 " << i << endl; 10 } 11 return 0; 12 }
(1)GCC 1019
(2)MSVC 109
超出上述max_size後,被系統拒絕insert了,我想那是它的極限了,不能突破。
至此,咱們對STL vector的實現就差很少了解了,出去侃侃也足夠了。
代碼來自《STL源碼解析》,源碼迸發着光輝!