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