STL源码剖析-vector
STL(Standard Template Library)
我们使用库函数非常方便,且非常高效(相对于自己实现来说)。那如此好用的模板库它的内里是什么样的?它背着我们施展了什么“魔法”呢?我决定一探究竟,相信你也是一样。我会选用部分重要代码做分析,用来提升自己,希望后来的你在我的拙见中也能有自己的收获。
vector
数据存储方式:线性存储(一块连续内存),类似array。
相比于内置数组(不是array哦)的优势:动态扩容。(其实也不算什么优势,数组也完全可以做,只不过它把扩容过程高效安全地封装了起来。)
相比于array,优势就更大了,array的容量开始就是定死了的,无法扩容。
使用方法
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std; // unique_ptr::get vs unique_ptr::release
int main()
{
//初始化
vector<int> vec;//声明,未初始化
vector<int> vec1(, );//2个5
vector<int> vec2 = { , , , , };//直接初始化
//读取元素
cout << "第2个元素: " << vec2[] << endl;
cout << "首元素: " << vec2.front() << endl;
cout << "尾元素: " << vec2.back() << endl;
//插入元素
vec1.insert(vec1.begin(), );//para1-插入位置,要迭代器即指针,para2-插入内容
vec2.push_back();//尾部插入
vec2.pop_back();//删除尾部,类似于stack,所以有时候也可以把vector当stack用
//删除元素
vec2.erase(vec2.end()-);//参数也是迭代器类型,所以使用insert和erase时,最好用iterator来遍历
//排序
sort(vec2.begin(), vec2.end());//给出首位指针
sort(vec2.begin(), vec2.begin()+);//甚至这样也可以,因为iterator本身就是类型指针 //遍历--下标索引访问
cout << "vec1 : " ;
for (int i = ; i < vec1.size(); ++i)
{
cout << vec1[i] << " ";
} //遍历--迭代器指针访问
cout << "\nvec2 : ";
vector<int>::iterator it;
for (it=vec2.begin(); it != vec2.end(); ++it)
{
cout << *it << " ";
}
41 //使用指针遍历vector
auto vec = new vector<int>(10, 8);
for(int i=0; i<vec->size(); i++)
cout << (*vec)[i] << " ";
return ;
}
好了,基本的用法就是这样。
底层是怎么实现的呢?
在STL源码中,vector类维护有三个迭代器(三个类型指针)start, finish, end_of_storage, 分别代表头, 尾(实际使用的), vector 存储尾部(占用的,通常大于实际使用)。

当我们vector<TYPE>::iterator it;时,it就是TYPE* 类型指针,上述三个迭代器也是如此。
库函数的实现呢?


我们可以看出,通过上述的三个指针,几乎所有的操作都可以进行了。值得一提的是vector重载了[ ],可以方便存取值。
需要注意的是,当我们访问尾元素时,迭代器可不是*.end(),而是*.end()-1。
那么我们再来探讨一下,有意思的东西。
插入元素时,预设的end_of_storage不够怎么办?怎么进行扩容。

再看源码!


整个的流程是:
1.先申请两倍内存,判断够不够,够进入2;否则,分配需要的大小;
2.拷贝要插入点之前的内容
3.构造插入元素顺次添加到后面
4.接着把之前插入点后面的内容拷贝到新的空间中
5.释放原来空间

来看一下GCC的vector扩容过程,大概是,不够就扩充为原来2倍,扩充为原来2倍还不够,则扩充至需要大小。
int main()
{
vector<int> vec;
for(int i=; i<; i++)
{
cout << "vector size= " << vec.size() << endl;
cout << "vector capacity= " << vec.capacity() << endl;
//cout << "vector max_size= " << vec.max_size() << endl;
vec.push_back(i);
}
cout << "最后一次, 插入100个元素 " << endl;
vec.insert(vec.begin(), , );
cout << "vector size= " << vec.size() << endl;
cout << "vector capacity= " << vec.capacity() << endl;
//cout << "vector max_size= " << vec.max_size() << endl; return ;
}

但是,vector最大空间是固定的。
我用同一段代码测试vector的最大空间 ,这里有一个疑问,要是超过额定最大空间又会怎么样?最后有尝试。
int main()
{
vector<int> vec;
for(int i=; i<; i++)
{
cout << "Max_size = " << vec.max_size() << endl;
cout << "size = " << vec.size() << endl;
vec.push_back(i);
cout << "插入 " << i << endl;
}
return ;
}
(1)GCC 1019

(2)MSVC 109

超出上述max_size后,被系统拒绝insert了,我想那是它的极限了,不能突破。
至此,我们对STL vector的实现就差不多了解了,出去侃侃也足够了。
代码来自《STL源码解析》,源码迸发着光辉!
STL源码剖析-vector的更多相关文章
- STL源码剖析读书笔记之vector
STL源码剖析读书笔记之vector 1.vector概述 vector是一种序列式容器,我的理解是vector就像数组.但是数组有一个很大的问题就是当我们分配 一个一定大小的数组的时候,起初也许我们 ...
- STL"源码"剖析-重点知识总结
STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略多 :) 1.STL概述 STL提供六大组件,彼此可以组合 ...
- 【转载】STL"源码"剖析-重点知识总结
原文:STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点 ...
- STL源码剖析 迭代器(iterator)概念与编程技法(三)
1 STL迭代器原理 1.1 迭代器(iterator)是一中检查容器内元素并遍历元素的数据类型,STL设计的精髓在于,把容器(Containers)和算法(Algorithms)分开,而迭代器(i ...
- STL"源码"剖析
STL"源码"剖析-重点知识总结 STL是C++重要的组件之一,大学时看过<STL源码剖析>这本书,这几天复习了一下,总结出以下LZ认为比较重要的知识点,内容有点略 ...
- 《STL源码剖析》相关面试题总结
原文链接:http://www.cnblogs.com/raichen/p/5817158.html 一.STL简介 STL提供六大组件,彼此可以组合套用: 容器容器就是各种数据结构,我就不多说,看看 ...
- STL源码剖析之序列式容器
最近由于找工作需要,准备深入学习一下STL源码,我看的是侯捷所著的<STL源码剖析>.之所以看这本书主要是由于我过去曾经接触过一些台湾人,我一直觉得台湾人非常不错(这里不涉及任何政治,仅限 ...
- STL源码剖析 — 空间配置器(allocator)
前言 以STL的实现角度而言,第一个需要介绍的就是空间配置器,因为整个STL的操作对象都存放在容器之中. 你完全可以实现一个直接向硬件存取空间的allocator. 下面介绍的是SGI STL提供的配 ...
- c++ stl源码剖析学习笔记(一)uninitialized_copy()函数
template <class InputIterator, class ForwardIterator>inline ForwardIterator uninitialized_copy ...
随机推荐
- C#净化版WebApi框架
前言 我们都知道WebApi是依赖于Asp.Net MVC的HttpRouteCollection进行路由 . 但WebApi和MVC之间是没有依赖关系的, WebApi的基类ApiControlle ...
- spring2.0 Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definiti
1. 报错信息 Description: The bean 'dataSource', defined in BeanDefinition defined in class path resource ...
- [ArcGIS API for JavaScript 4.8] Sample Code-Popups-1-popupTemplate的概念和popup中属性字段值的多种表现形式
[官方文档:https://developers.arcgis.com/javascript/latest/sample-code/intro-popuptemplate/index.html] 一. ...
- sqlserver笔记----创建用户赋予权限
1.创建用户: create login username with password='密码' , default_database=数据库; create user username for lo ...
- SQL SERVER 查看所有存储过程或视图里 包含某个关键字的查询语句
SELECT name, type_desc FROM sys.all_sql_modules s INNER JOIN sys.all_objects o ON s.object_id = o.ob ...
- 管道及I/O重定向
管道及IO 重定向 > < >> <<计算机组成: 运算器,控制器:CPU 存储器:RAM 输入/输出设备 I/O 程序: 指令和数据 控制器:指令 运算器: 存储 ...
- 信利SC123金融财务计算器评测——不错的HP 12C仿品
最近X宝48包邮购入信利SC123金融计算器,只是为了玩一玩(没错你的好友盗版狂魔又上线了),因为这是目前市面上能买到的最便宜的金融计算器了,也是能买到的最便宜的RPN计算器,顺手出个评测.这个计算器 ...
- 关于OSError: [WinError 10038] 在一个非套接字上尝试了一个操作。
在使用socket的时候,写了一个while循环,就报错了.结果如下: OSError: [WinError 10038] 在一个非套接字上尝试了一个操作. 代码 import socket impo ...
- Kafka的partions和replication-factor参数的理解
Topic在Kafka中是主题的意思,生产者将消息发送到主题,消费者再订阅相关的主题,并从主题上拉取消息. 在创建Topic的时候,有两个参数是需要填写的,那就是partions和replicatio ...
- centos6.7 配置Elasticsearch
Elasticsearch(以下简称ES),是一款开源的全文搜索引擎,获得了广泛的应用.这篇博客将介绍在centos6.7上如何配置ES. 一.安装JAVA环境 centos默认安装了JAVA环境,首 ...