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 ...
随机推荐
- SpringCloud学习系列之一 ----- 搭建一个高可用的注册中心(Eureka)
前言 本篇主要介绍的是SpringCloud相关知识.微服务架构以及搭建一个高可用的服务注册与发现的服务模块(Eureka). SpringCloud介绍 Spring Cloud是在Spring B ...
- Asp.Net Core 轻松学-多线程之Task(补充)
前言 在上一章 Asp.Net Core 轻松学-多线程之Task快速上手 文章中,介绍了使用Task的各种常用场景,但是感觉有部分内容还没有完善,在这里补充一下. 1. 任务的等待 在使用 ...
- 如何通过get,set方法访问到父类的私有属性
刚学习继承的时候,总是会有这样的疑问. 子类继承父类时,会继承所有的非私有的属性和方法.那么在用set方法修改父类的私有属性时,怎么没有报空指针异常呢? 后来仔细想过这个问题,既然没有报空指针,那么在 ...
- Rest_framework Serializer 序列化 (含源码浅解序列化过程)
目录 Rest_framework Serializer 序列化 序列化与反序列化中不得不说的感情纠葛 三角恋之 save/update/create 四角恋之 序列化参数instance/data/ ...
- 对 MES 感兴趣?赶紧看过来!
在知乎许久都没有智能制造话题,索性自己在 2018-06-08 创建了智能制造话题,在创建话题过程中也遇到些麻烦,最终联系了知乎小管家,成功创建了该话题.目前过去7个月了,该话题的关注人数有820人了 ...
- PyQt5 api 帮助文档
学习PyQt5的帮助文档是通过,使用help(PyQt5 class)的方式在console端输出帮助内容,常用的方法和属性查找起来不是很方便,现在放在网上以方便大家使用. QWidget Qt QM ...
- Linux 桌面玩家指南:07. Linux 中的 Qemu、KVM、VirtualBox、Xen 虚拟机体验
特别说明:要在我的随笔后写评论的小伙伴们请注意了,我的博客开启了 MathJax 数学公式支持,MathJax 使用$标记数学公式的开始和结束.如果某条评论中出现了两个$,MathJax 会将两个$之 ...
- AutoHotkey 自动化脚本工具实例
AHK 自动按键工具 https://www.autohotkey.com/ 可实现功能 快捷键 启动 浏览器.CMD命令.弹出框 可定时执行任务 可改键 将A与B互换 可快捷替换字符串 测试如下: ...
- JAVA类的继承之多态特性
父类可以接收子类的实例,方法的覆盖,属性的隐藏,这些都使我非常疑惑,今天有点时间记录之. 话不多说,直接上代码上结果 1. public class TestDto{ public static vo ...
- Spring Cloud Eureka 常用配置详解,建议收藏!
前几天,栈长分享了 <Spring Cloud Eureka 注册中心集群搭建,Greenwich 最新版!>,今天来分享下 Spring Cloud Eureka 常用的一些参数配置及说 ...