C++vector的push_back擴容機制為什麼不考慮在尾元素後面的空間申請記憶體?山海皆可平z2020-04-04 15:08:12

vector是整塊記憶體佔用,記憶體地址是連續的,一般情況下已經沒有剩餘的記憶體在原來的記憶體後面,這個時候就需要另外新建一個更大的連續記憶體空間,然後把資料複製過去,最後釋放原來的記憶體。 所以vector最好是對於記憶體有個預先的評估和計算, 頻繁的整塊切換記憶體地址,這個開銷也是蠻大的。

C++vector的push_back擴容機制為什麼不考慮在尾元素後面的空間申請記憶體?編碼之道2020-04-07 21:11:59

首先我們看一下官方文件對vector的說明:

C++vector的push_back擴容機制為什麼不考慮在尾元素後面的空間申請記憶體?

再看一下對push_back函式的說明:

C++vector的push_back擴容機制為什麼不考慮在尾元素後面的空間申請記憶體?

總結起來就是初始時刻vector的capacity為0,塞入第一個元素後capacity增加為1,vector內部是透過陣列來實現的,它佔用的是一塊連續空間,當空間不足時它會重新申請空間,並將當前內容一併複製到新的空間,下圖是vector記憶體的擴充的示意圖。

C++vector的push_back擴容機制為什麼不考慮在尾元素後面的空間申請記憶體?

有一點需要說明,容量擴充並不總是擴充至兩倍,具體的倍數取決於編譯器,比如在GCC下是兩倍,而在VS2017中是1。5倍,下圖是在VS中的實驗結果。

C++vector的push_back擴容機制為什麼不考慮在尾元素後面的空間申請記憶體?

可見每push_back一個元素,vector的size就增加1,而capacity則以1。5倍的速度增加,3增加到4而不是4。5,是因為取整的原因。

那麼為什麼要這樣處理,主要有兩個原因:

1、vector在push_back以成倍增長可以在均攤後達到O(1)的事件複雜度。具體的推理過程涉及到演算法分析與一些數學知識,在此不再傲述,感興趣的話,可留言。

2、考慮可能產生的堆空間浪費,成倍增長倍數不能太大,為了防止申請記憶體的浪費,現在使用較多的有2倍與1。5倍的增長方式,而1。5倍的增長方式可以更好的實現對記憶體的重複利用。

至於問題中的為什麼不在vector結尾處申請記憶體,那是因為每次申請的記憶體由系統決定,程式和編譯器並不能控制。

C++vector的push_back擴容機制為什麼不考慮在尾元素後面的空間申請記憶體?IM小行星2020-04-04 12:25:43

分兩種情況,容器隊尾若有剩餘未使用空間,可以直接插入,否則會重新申請一片更大的區域,並將原區域資料複製到新區域,並指向新區域的地址。到這種操作是自動完成的,使用者並不感知。