搞定技术面试:那些你可能不知道的 vector 和 array 的区别

最近几年,计算机工做愈加难找,你必须比其余人了解的更多,才能有更多的机会找到一个更好的工做。html

C++ 标准库(STL)是不少C++面试中都会问到的问题,不少不少问题会关于 Vector 的空间分配、动态增加之类的问题,那么你了解 STL 中那些顺序容器的区别与联系吗? 你知道在什么状况选用什么容器吗?面试

先说结论,通常状况选择 vector 是很好的选择,若是你的程序目标有以下特色时,才可能须要换用别的容器:数组

  • 有不少小元素、空间额外开销比较重要,不要使用 list 和 forward_list;
  • 程序要求随机访问,选择 vector 和 deque;
  • 程序常常在中间插入元素,能够选择 list 和 forward_list;
  • 程序只在头尾插入元素,不常在中间插入元素,选择 deque;
  • 程序一开始插入时会在中间插入元素,但以后的使用过程当中基本不在中间插入元素,先用 list 处理输入场景,再用 vector 拷贝 list 的数据,处理后续使用。

总体介绍

全部的顺序容器都具备能够快速按顺序访问元素的能力,但每种容器在具体的实现上又有些区别。函数

顺序容器类型 含义 特色
vector 可变大小数组 随机访问快、尾部插入元素快、其余位置插入、删除元素慢
deque 双端队列 随机访问快、头尾插入元素快
list 双向链表 只支持双向顺序访问、在任何位置插入、删除元素都很快
forward_list 单向链表 只支持从前日后的单向顺序访问、在任何位置插入删除元素都很快
array 固定大小数组 随机访问快、容器大小固定不支持插入删除元素
string 字符串,相似vector,专门保存字符、随机访问快、在尾部插入删除元素快

按类型介绍

vector string

vector 和 string 将元素保存在连续的内存空间中,分配一段连续的内存空间进行存储,其迭代器采用 C++ 指针便可,所以其支持随机访问和存储,支持下标操做符,节省空间。可是其在分配的内存不够的状况下,须要对容器总体进行从新分配、拷贝和释放等操做(空间的动态增加),并且在 vector 和 string 中间插入或删除元素效率很低。性能

vector的内存分配实现原理:STL内部实现时,首先分配一个很是大的内存空间预备进行存储,即capacity()函数返回的大小,当超过此分配的空间时再总体从新放分配一块内存存储(VS6.0是两倍,VS2005是1.5倍),因此这给人以vector能够不指定vector即一个连续内存的大小的感受。一般此默认的内存分配能完成大部分状况下的存储。.net

扩充空间(不论多大)都应该这样作:指针

  1. 配置一块新空间
  2. 将旧元素一一搬往新 址
  3. 把原来的空间释放还给系统

list forward_list

list 和 forward_list 是以节点形式来存放数据,使用的是非连续的内存空间来存放数据,所以,在其内部插入和删除元素的时间复杂度都是O(1),可是其不支持随机访问和存取,不支持下标;由于每一个结点须要额外空间存储链接的状况,他们比 vector 占用的内存要多不少。code

list 是非连续存储结构,具备双链表结构,每一个元素维护一对前向和后向指针,所以支持前向/后向遍历。支持高效的随机插入/删除操做,但随机访问效率低下,且因为须要额外维护指针,开销也比较大。每个结点都包括一个信息快Info、一个前驱指针Pre、一个后驱指针Post。能够不分配必须的内存大小方便的进行添加和删除操做。使用的是非连续的内存空间进行存储。cdn

forward_list 底层实现上是单链表,且实质上无任何多余开销,与 list 相比,此容器在不须要双向迭代时提供更有效地利用空间的存储。在链表内或跨数个链表添加、移除和移动元素,不会非法化当前指代链表中其余元素的迭代器。forward_list 的迭代器不支持iter--操做,即不支持反向迭代;同时 forward_list 也不支持size()操做。htm

deque

vector是一个单向开口的容器,deque则是一个双向开口的容器,所谓双向开口就是再头尾两端都可以作元素的插入和删除操做。

deque 在空间增加上与 vector 不一样,它是动态的以分段的连续空间组合而成,随时能够增长一段空间链接起来。 所以,为了管理多段链接,deque有中控器的概念,此处实现上详细状况的请参见《STL源码剖析》

array

array 与内置数组相似,大小是固定的,所以不支持增长元素、删除元素以及改变容器大小的功能。 在使用 array 时,必须同时指定元素类型和大小array<int,20>

此容器是一个聚合类型,其语义等同于保有一个 C 风格数组 T[N] 做为其惟一非静态数据成员的结构体。该结构体结合了 C 风格数组的性能、可访问性与容器的优势,好比可获取大小、支持赋值、随机访问迭代器等。

迭代器 Iterator

迭代器的范围都是左开右闭,理解为数学上的区间则是 [xx.begin(), xx.end()),左边是能够达到的,右边是达不到的。

Reference

  1. C++ Primer 5th
  2. STL 源码剖析
  3. Cppreference
  4. CSDN:C++三种容器:list、vector和deque的区别
相关文章
相关标签/搜索