STL源码剖析-vector

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源码解析》,源码迸发着光辉!

相关文章
相关标签/搜索