C C 標準庫容器vector的用法及記憶體管理

2021-08-23 14:17:42 字數 3477 閱讀 7880

c++中的標準庫容器vector是乙個類模板,可以根據想裝入元素的具體型別來例項化乙個vector容器,vector相當於乙個動態陣列,當你無法知道自己需要的陣列規模具體要多大時,可以用它來解決問題,而且使用很方便。

#include #include int main()

1. push_back           在陣列的最後新增乙個資料

2. pop_back 去掉陣列的最後乙個資料

3. at 得到編號位置的資料

4. begin 得到陣列頭的指標

5. end 得到陣列的最後乙個單元+1的指標

6.front 得到陣列頭的引用

7. back 得到陣列的最後乙個單元的引用

8. max_size 得到vector最大可以是多大

9. capacity 當前vector分配的大小

10.size 當前使用資料的大小

11.resize 改變當前使用資料的大小,如果它比當前使用的大,者填充預設值

12.reserve 改變當前vector所分配空間的大小

13.erase 刪除指標指向的資料項

14.clear 清空當前的vector

15.rbegin 將vector反轉後的開始指標返回(其實就是原來的end-1)

16.rend 將vector反轉構的結束指標返回(其實就是原來的begin-1)

17.empty 判斷vector是否為空

18.swap 與另乙個vector交換資料

(1) 使用reserve()函式提前設定容量大小,避免多次容量擴充操作導致效率低下。

stl容器最令人稱讚的特性之一就是只要不超過它們的最大容量,它們就可以自動增長到足以容納你放入的資料。(要知道這個最大值,只要呼叫名叫max_size的成員函式。)對於vector和string,如果需要更多空間,就以類似realloc的思想來擴充空間。vector容器支援隨機訪問,因此為了提高效率,它內部使用動態陣列的方式實現的。在通過 reserve() 來申請特定大小的時候總是按指數邊界來增大其內部緩衝區。當進行insert或push_back等增加元素的操作時,如果動態陣列的記憶體不夠用,就要動態的重新分配當前大小的1.5~2倍的新記憶體區,再把原陣列的內容複製過去。所以在一般情況下,其訪問速度同一般陣列,只有在重新分配發生時,其效能才會下降。正如上面的**告訴你的那樣。而進行pop_back操作時,capacity並不會因為vector容器裡的元素減少而有所下降,還會維持操作之前的大小。對於vector容器來說,如果有大量的資料需要進行push_back,應當使用reserve()函式提前設定其容量大小,否則會出現許多次容量擴充操作,導致效率低下。

reserve成員函式允許你最小化必須進行的重新分配的次數,因而可以避免重新分配的開銷和迭代器/指標/引用失效。但在我解釋reserve為什麼可以那麼做之前,讓我簡要介紹有時候令人困惑的四個相關成員函式。在標準容器中,只有vector和string提供了所有這些函式。

這個簡介表示了只要有元素需要插入而且容器的容量不足時就會發生重新分配(包括它們維護的原始記憶體分配和**,物件的拷貝和析構和迭代器、指標和引用的失效)。所以,避免重新分配的關鍵是使用reserve盡快把容器的容量設定為足夠大,最好在容器被構造之後立刻進行。

例如,假定你想建立乙個容納1-1000值的vector。沒有使用reserve,你可以像這樣來做:

vectorv;

for (int i = 1; i <= 1000; ++i) v.push_back(i);

在大多數stl實現中,這段**在迴圈過程中將會導致2到10次重新分配。(10這個數沒什麼奇怪的。記住vector在重新分配發生時一般把容量翻倍,而1000約等於210。)

把**改為使用reserve,我們得到這個:

vectorv;

v.reserve(1000);

for (int i = 1; i <= 1000; ++i) v.push_back(i);

這在迴圈中不會發生重新分配。

在大小和容量之間的關係讓我們可以預言什麼時候插入將引起vector或string執行重新分配,還可以預言什麼時候插入會使指向容器中的迭代器、指標和引用失效。例如,給出這段**

string s;

...if (s.size() < s.capacity())

push_back的呼叫不會使指向這個string中的迭代器、指標或引用失效,因為string的capacity容量保證大於它的size大小。如果不是執行push_back,**在string的任意位置進行乙個insert,我們仍然可以保證在插入期間沒有發生重新分配,但是,與伴隨string插入時迭代器失效的一般規則一致,所有從插入位置到string結尾的迭代器/指標/引用將失效。

回到本條款的主旨,通常有兩情況使用reserve來避免不必要的重新分配。第乙個可用的情況是當你確切或者大約知道有多少元素將最後出現在容器中。那樣的話,就像上面的vector**,你只是提前reserve適當數量的空間。第二種情況是保留你可能需要的最大的空間,然後,一旦你新增完全部資料,修整掉任何多餘的容量。

(2) 使用「交換技巧」來修整vector過剩空間/記憶體

有一種方法來把它從曾經最大的容量減少到它現在需要的容量。這樣減少容量的方法常常被稱為「收縮到合適(shrink to fit)。該方法只需一條語句:vector(ivec).swap(ivec);

表示式vector(ivec)建立乙個臨時vector,它是ivec的乙份拷貝,vector的拷貝建構函式做了這個工作。但是,vector的拷貝建構函式只分配拷貝的元素需要的記憶體,所以這個臨時vector沒有多餘的容量。然後我們讓臨時vector和ivec交換資料,這時我們完成了,ivec只有臨時變數的修整過的容量,而這個臨時變數則持有了曾經在ivec中的沒用到的過剩容量。在這裡(這個語句結尾),臨時vector被銷毀,因此釋放了以前ivec使用的記憶體,收縮到合適。

(3) vector 記憶體管理成員函式的行為測試

c++ stl的vector使用非常廣泛,但是對其記憶體的管理模型一直有多種猜測,下面用例項**測試來了解其記憶體管理方式,測試**如下:

#include #include using namespace std;

int main()

不同開發環境容量增長的方式可能不相同,vs2017裡面就不是指數增長。

vector變數本身的實現就類似於乙個管理堆記憶體的指標,所以vector變數無論如何變化,sizeof(vector)是不會變化的。

c 標準庫 容器類

容器類可以分為兩大類和容器介面卡 1 序列容器 sequence containers 這種容器中的元素是有序的,每乙個元素在容器中都有乙個確切的位置,這個位置不依賴於元素的值,而是跟放入容器的時機有關。標準的序列容器有三個 vector,deque,list。另外你也可以把字串 string 和陣...

C 標準庫容器 Map

本部落格主要簡述了c 標準庫容器map的一些特性 map 的定義及特性 乙個map就是乙個 關鍵碼,值 對偶的序列,它提供基於關鍵碼的快速提取操作。每個關鍵碼至多保持乙個值,換句話說,map中的關鍵碼具有唯一性。簡單來說,map提供了乙個對映關係來查詢元素。map的部分成員 成員定義備註 key關鍵...

STL標準庫 容器 forward list

forward list即單向list,功能少額外開銷就小.而且只能在前段插入元素 結構如下 一 定義 include int main int argc,const char ar return0 二 與迭代器的使用 由於forward list的迭代器內指向記憶體不連續 顧不能做迭代器 操作 i...