搞定技術面試:那些你可能不知道的 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的區別
相關文章
相關標籤/搜索