•  什么是容器

    容器,顾名思义,是用来容放东西的场所。C++容器容放某种数据结构,以利于对数据的搜寻或排序或其他特殊目的。众所周知,常用的数据结构不外乎:数组array,  链表list,  树tree,  栈stack,  队列queue,  散列表hash table,  集合set、映射表map 等等。容器便是容纳这些数据结构的。这些数据结构分为序列式与关联式两种,故容器也分为序列式容器和关联式容器。

 

                   (图来自《STL源码剖析》)

 

 

  • vector容器

1.  vector是STL提供的一种序列式容器  

  所谓序列式容器,其中的元素都序,但未必有序,即元素集合呈线性关系排列,但未必是有序的。C++本身带了一种序列式容器array,STL再提供其他的序列式容器:vector,list,deque,stack,queue,priority-queue等。

2.   vector底层为动态数组

  vector的数据安排以及操作方式与C++的array十分相似,它们间的唯一差别在于对空间的运用灵活性上。array为静态数组,有着静态数组最大的缺点:每次只能分配一定大小的存储空间,当有新元素插入时,要经历  “找到更大的内存空间”->“把数据复制到新空间” ->“销毁旧空间” 三部曲, 且对于array而言,这种空间任务压在使用它的用户身上,用户必须把握好数据的数量,尽量在第一次分配时就给数据分配合理的空间(这有时很难做到),以防止“三部曲”带来的代价,而数据溢出也是静态数组使用者需要注意的问题。

  而vector用户不需要亲自处理空间运用问题。vector是动态空间,随着新元素的插入,旧存储空间不够用时,vector内部机制会自行扩充空间以容纳新元素,当然,这种空间扩充大部分情况下(几乎是)也逃脱不了“三部曲”,只是不需要用户自己处理,而且vector处理得更加安全高效。vector的实现技术关键就在于对其大小的控制以及重新配置时数据移动效率。

3.  vector的迭代器

  对于C语言的数组,我们使用普通指针就可以对数组进行各种操作。vector维护的是一个连续线性空间,与数组array一样,所以无论其元素型别为何,普通指针都可以作为vector的迭代器而满足所有必要的条件。vector所需要的迭代器操作,包括operator*,operator->,operator++,operator--,operator+=,operator-=等,普通指针都具有。

  故,普通指针即可满足vector对迭代器的需求。所以,vector提供了Random Access Iterators。

4. vector的数据结构

  正如上面所说,vector底层为连续线性空间。它使用两个迭代器:begin与finish该连续线性空间中的第一个元素的位置与超出末端的第一位位置,这两个迭代器标志了连续线性空间的已使用范围,并以end_of_storage迭代器标准整个连续线性空间的尾端。这里begin与finish符合STL“前开后闭”的标准。

  

  基于这三个迭代器,可以完成许多操作。包括提供首尾标示、大小、容量、空容器判断、[]运算符、最前端元素值、最后端元素值等等。

  值得注意的是,容器的大小与容量是不一样的概念。只有在容器满载时,大小才等于容器。在上面这张图中,大小size为已使用的存储空间长度,而容量为已使用+未使用的存储空间长度。从它们的实现代码上也可以看出来:

  

size_type size() const
{return size_type( end() - begin() ) ;
}size_type capacity () const
{return size_type( end_of_storage - begin() );
}

5. vector的内存分配策略

  标准库的实现者使用了这样的内存分配策略:以最小的代价连续存储元素。为了使vector容器实现快速的内存分配,其实际分配的容量要比当前所需的空间多一些,vector容器预留了这些额外的存储区用于存放添加的新元素,于是不必为每个新元素进行一次内存分配。当继续向容器中加入元素导致备用空间被用光(超过了容量 capacity),此时再加入元素时vector的内存管理机制便会扩充容量至两倍,如果两倍容量仍不足,就扩张至足够大的容量。容量扩张必须经历“重新配置、元素移动、释放原空间”这个浩大的工程。按照《STL源码剖析》中提供的vector源码,vector的内存配置原则为:

  如果vector原大小为0,则配置1,也即一个元素的大小。

  如果原大小不为0,则配置原大小的两倍。

  当然,vector的每种实现都可以自由地选择自己的内存分配策略,分配多少内存取决于其实现方式,不同的库采用不同的分配策略。

  需要注意的是,使用vector迭代器时要时刻注意vector是否发生了扩容,一旦扩容引起了空间重新配置,指向原vector的所有迭代器都将失效。 

  关于vector各种接口的使用方法这里就不再赘述了。对于vector有新认识会及时更新博文。

  

  

转载于:https://www.cnblogs.com/QG-whz/p/4558147.html

C++ 序列式容器之vector相关推荐

  1. STL源码剖析(十三)关联式容器之rb_tree

    STL源码剖析(十三)关联式容器之rb_tree 文章目录 STL源码剖析(十三)关联式容器之rb_tree 一.rb_tree的数据结构 二.rb_tree的迭代器 三.rb_tree的操作 3.1 ...

  2. STL容器之vector

    [1]模板类vector 模板类vector可理解为广义数组.广义数组,即与类型无关的数组,具有与数组相同的所有操作. 那么,你或许要问:既然C++语言本身已提供了一个序列式容器array,为什么还要 ...

  3. C++序列容器之 vector常见用法总结

    http://www.cnblogs.com/YJthua-china/p/6550960.html

  4. c++容器之vector

    定义:vector 是一个动态存储任何对象的序列容器. 头文件:#include<vector> 初始化: 1. vector<T> v;   创建一个空的vector容器v, ...

  5. 【STL源码剖析读书笔记】【第5章】关联式容器之hashtable

    1.hashtable在插入.删除.搜寻操作上具有"常数平均时间"的表现,不依赖输入元素的随机性. 2.hashtable通过hashfunction将元素映射到不同的位置,但当不 ...

  6. 顺序容器之vector

    最近因为需要,在看C++ primer,哇,感觉这本书真不错,讲的细而且到位,而且大量的练习题,不愧为C++学习的经典书籍.今天看了顺序容器方面的内容,现在汇报一下: 一.什么是vector vect ...

  7. 【STL源码剖析读书笔记】【第5章】关联式容器之set、map、multiset和multimap

    一.set 1.  set的特性是所有元素都会根据元素的键值自动排序,set元素的键值就是实值,实值就是键值. 2.  不能通过set的迭代器改变set的元素,setiterators是一种const ...

  8. [知识点]C++中STL容器之set

    零.STL目录 1.容器之map 2.容器之vector 3.容器之set 一.前言 继上期的vector之后,我们又迎来了另一个类数组的STL容器--set. 二.用途与特性 set,顾名思义,集合 ...

  9. STL容器之deque

    双端队列:序列式容器(deque/vector):底层分段连续 支持从双端进行插入和删除: 综合了vector和list的优点: 插入.删除.查找的平均时间复杂度都是O(1) 部分deque的操作如下 ...

最新文章

  1. [Spring mvc 深度解析(一)] 详解Servlet
  2. 记录安装oracle的那些事(二)之双系统安装
  3. Kubernetes — 容器与镜像
  4. apple的photo实际上是一个dashboard
  5. Java 读书笔记 (十一) Number Math 类
  6. linux mint 18 mysql_linux mint下mysql中文支持问题
  7. 吴裕雄 python 神经网络——TensorFlow训练神经网络:不使用隐藏层
  8. python截图拼接_Python实现屏幕截图有两种方式 - 小众知识
  9. 还是想继续写代码,不想这么快就去养猪~
  10. C++匿名函数Lambda
  11. 团队作业三——项目思考
  12. 苹果电脑忘记开机密码怎么办?一段代码轻松解决
  13. Emacs帮你进行英文写作
  14. 真正免费的天气API,无需注册申请key
  15. 新手怎么选择蓝牙耳机不被忽悠?注意这两大误区一定不猜雷
  16. 进制转换之十进制转换为十六进制
  17. java面试常见设计模式
  18. matlab计算器设计流程图_matlab计算器的设计.doc
  19. 分类任务如何用逻辑回归实现_【机器学习面试总结】—— LR(逻辑回归)
  20. 鸿蒙系统和安卓的区别在哪里,有什么不同

热门文章

  1. Java 项目 接口开发规范
  2. 3.7 为什么需要非线性激活函数?
  3. ESXI6.7虚拟机配置LACP静态汇聚端口网络负载均衡分流
  4. Docker学习总结(8)——利用Docker开启持续交付之路
  5. c语言迷宫求解毕业设计,毕业设计(论文)-基于Windows平台C语言实现迷宫游戏的设计.doc...
  6. 电脑排行榜笔记本_2019联想笔记本电脑排行榜
  7. Java设计模式之单例模式(七种写法)
  8. set是无序集合,放入set中的元素通过iterator输出时候是无序的
  9. AFNnetworking详解
  10. [HDU 4842]--过河(dp+状态压缩)