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 ...
随机推荐
- 关于vue使用form上传文件
在vue中使用form表单上传文件文件的时候出现了一些问题,获取文件的时候一直返回null, 解决之后又出现发送到后台的file文件后台显示为空,解决源码 <template> <d ...
- 拼多多大数据开发工程师SQL实战解析
不久前,裸考国内知名电商平台拼多多的大数据岗位在线笔试,问答题(写SQL)被虐的很惨,完了下来默默学习一波.顺便借此机会复习一下SQL语句的用法. 本文主要涉及到的SQL知识点包括CREATE创建数据 ...
- 第13章 Base64 URL编码 - IdentityModel 中文文档(v1.0.0)
JWT令牌使用Base64 URL编码进行序列化. IdentityModel包括Base64Url帮助编码/解码的类: var text = "hello"; var b64ur ...
- java.lang.UnsatisfiedLinkError:dlopen failed: “**/*/arm/*.so” has unexpected e_machine: 3
转载请标明出处,维权必究:https://www.cnblogs.com/tangZH/p/10458448.html 今天在做APP的时候使用so库,可结果一加载so库的时候便发生了这个莫名其妙的错 ...
- PowerDesigner如何连接数据库--odbc连接数据库用法
先下载msi https://dev.mysql.com/downloads/connector/odbc/ 注:如果不成功,有可能msi版本问题,可以更换一下msi 前期准备 双击odbc的ms ...
- windows下nginx的安装及使用
安装过程比较简单 1.下载nginx http://nginx.org/en/download.html 下载稳定版本,以nginx/Windows-1.14.2为例,直接下载 nginx-1.14. ...
- 零基础java的福音!史上最全最精简的学习路线图!
这是一个java系统学习路线,从零基础到项目框架开发,每一个阶段里面内容都标记的很清楚,如果你现在也在学习java,你可以跟着这个系统学习路线学,学完自己可以独立的完成项目框架开发,二线城市拿个7k+ ...
- JNI实战(四):C 调用 Java
在前面我们讲了一下如何使用Java调用C,本文我们讲一下如何使用JNI提供的接口来反射得到Java方法进行调用. 主要步骤如下: FindClass (找到Java层的类) GetMethodID / ...
- N元模型
在自然语言处理的任务中,拼音纠错.机器翻译等任务都需要对某个句子的下一个单词进行预测,或者评估某个句子的概率大小.例如预测如下句子的下一个单词: Please turn your home work. ...
- MySQL命令窗口下中文显示乱码的解决过程
在dos客户端输出窗口中查询表中的数据,还有项目部署到服务器上时前台的页面,中文数据都显示成乱码,如下图所示: 这个问题困扰了我一天,后来解决了才发现原来我的方向错了,一直我以为是SpringBoot ...