C 中vector的用法

2021-06-26 15:55:34 字數 4819 閱讀 7880

c++內建的陣列支援容器的機制,但是它不支援容器抽象的語義。要解決此問題我們自己實現這樣的類。在標準c++中,用容器向量(vector)實現。容器向量也是乙個類模板。

標準庫vector型別使用需要的標頭檔案:#include 。vector 是乙個類模板。不是一種資料型別,vector是一種資料型別。vector的儲存空間是連續的,list不是連續儲存的。

一、 定義和初始化

vector< typename > v1;       //預設v1為空,故下面的賦值是錯誤的v1[0]=5;

vectorv2(v1); 或v2=v1;或vectorv2(v1.begin(), v1.end());//v2是v1的乙個副本,若v1.size()>v2.size()則賦值後v2.size()被擴充為v1.size()。

vector< typename > v3(n,i);//v3包含n個值為i的typename型別元素

vector< typename > v4(n); //v4含有n個值為0的元素

int a[4]=; vectorv5(a,a+5);//v5的size為5,v5被初始化為a的5個值。後乙個指標要指向將被拷貝的末元素的下一位置。

vectorv6(v5);//v6是v5的拷貝

vector< 型別 > 識別符號(最大容量,初始所有值);

二、 值初始化

1>     如果沒有指定元素初始化式,標準庫自行提供乙個初始化值進行值初始化。

2>     如果儲存的式含有建構函式的類型別的元素,標準庫使用該型別的建構函式初始化。

3>     如果儲存的式沒有建構函式的類型別的元素,標準庫產生乙個帶初始值的物件,使用這個物件進行值初始化。

三、vector物件最重要的幾種操作

1. v.push_back(t)    在容器的最後新增乙個值為t的資料,容器的size變大。

另外list有push_front()函式,在前端插入,後面的元素下標依次增大。

2. v.size()        返回容器中資料的個數,size返回相應vector類定義的size_type的值。v.resize(2*v.size)或                  

v.resize(2*v.size, 99) 將v的容量翻倍(並把新元素的值初始化為99)

3. v.empty()     判斷vector是否為空

4. v[n]           返回v中位置為n的元素

5. v.insert(pointer,number, content)    向v中pointer指向的位置插入number個content的內容。

還有v. insert(pointer, content),v.insert(pointer,a[2],a[4])將a[2]到a[4]三個元素插入。

6. v.pop_back()    刪除容器的末元素,並不返回該元素。

7.v.erase(pointer1,pointer2) 刪除pointer1到pointer2中間(包括pointer1所指)的元素。

vector中刪除乙個元素後,此位置以後的元素都需要往前移動乙個位置,雖然當前迭代器位置沒有自動加1,

但是由於後續元素的順次前移,也就相當於迭代器的自動指向下乙個位置一樣。

8. v1==v2          判斷v1與v2是否相等。

9. !=、<、<=、>、>=      保持這些操作符慣有含義。

10. vector::iterator p=v1.begin( ); p初始值指向v1的第乙個元素。*p取所指向元素的值。

對於const vector只能用vector::const_iterator型別的指標訪問。

11.   p=v1.end( ); p指向v1的最後乙個元素的下一位置。

12.v.clear()      刪除容器中的所有元素。12.v.clear()      刪除容器中的所有元素。

#include中的泛函演算法

搜尋演算法:find() 、search() 、count() 、find_if() 、search_if() 、count_if()

分類排序:sort() 、merge()

刪除演算法:unique() 、remove()

生成和變異:generate() 、fill() 、transformation() 、copy()

關係演算法:equal() 、min() 、max()

sort(v1.begin(),vi.begin()+v1.size/2); 對v1的前半段元素排序

list::iterator pmiddle =find(clist.begin(),clist.end(),'a');找到則返回被查內容第一次出現處指標,否則返回end()。

vector< typename >::size_type x ; vector< typename >型別的計數,可用於迴圈如同for(int i)

初學c++的程式設計師可能會認為vector的下標操作可以新增元素,其實不然:

vectorivec;   // empty vector

for (vector::size_type ix = 0; ix != 10; ++ix)

ivec[ix] = ix; // disaster: ivec has no elements

上述程式試圖在ivec中插入10個新元素,元素值依次為0到9的整數。但是,這裡ivec是空的vector物件,而且下標只能用於獲取已存在的元素。

這個迴圈的正確寫法應該是:

for (vector::size_type ix = 0; ix != 10; ++ix)

ivec.push_back(ix); // ok: adds new element with value ix

警告:必須是已存在的元素才能用下標操作符進行索引。通過下標操作進行賦值時,不會新增任何元素。僅能對確知已存在的元素進行下標操作 

四、記憶體管理與效率

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提供了所有這些函式。

(1) size()告訴你容器中有多少元素。它沒有告訴你容器為它容納的元素分配了多少記憶體。

(2) capacity()告訴你容器在它已經分配的記憶體中可以容納多少元素。那是容器在那塊記憶體中總共可以容納多少元素,而不是還可以容納多少元素。如果你想知道乙個vector或string中有多少沒有被占用的記憶體,你必須從capacity()中減去size()。如果size和capacity返回同樣的值,容器中就沒有剩餘空間了,而下一次插入(通過insert或push_back等)會引發上面的重新分配步驟。

(3) resize(container::size_type n)強制把容器改為容納n個元素。呼叫resize之後,size將會返回n。如果n小於當前大小,容器尾部的元素會被銷毀。如果n大於當前大小,新預設構造的元素會新增到容器尾部。如果n大於當前容量,在元素加入之前會發生重新分配。

(4) reserve(container::size_type n)強制容器把它的容量改為至少n,提供的n不小於當前大小。這一般強迫進行一次重新分配,因為容量需要增加。(如果n小於當前容量,vector忽略它,這個呼叫什麼都不做,string可能把它的容量減少為size()和n中大的數,但string的大小沒有改變。在我的經驗中,使用reserve來從乙個string中修整多餘容量一般不如使用「交換技巧」,那是條款17的主題。)

這個簡介表示了只要有元素需要插入而且容器的容量不足時就會發生重新分配(包括它們維護的原始記憶體分配和**,物件的拷貝和析構和迭代器、指標和引用的失效)。所以,避免重新分配的關鍵是使用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執行重新分配,而且,可以預言什麼時候插入會使指向容器中的迭代器、指標和引用失效。例如,給出這段**,

C 中vector的用法

1 在使用前要包含vector對應的標頭檔案 include 2 vector是同一種型別的物件的集合,每個物件都有乙個對應的整數索引值。我們把vector稱為容器,乙個容器中的所有物件都必須是同一種型別的。3 vector是乙個類模板 class template 模板允許程式設計師編寫單個類或函...

c 中的vector用法

在c 中,vector是乙個十分有用的容器,下面對這個容器做一下總結。1 基本操作 1 標頭檔案 include.2 建立vector物件,vectorvec 3 尾部插入數字 vec.push back a 4 使用下標訪問元素,cout vector iterator it for it vec...

C 中vector的用法

一 基本操作 1.標頭檔案 include 2.建立物件a vector a 定義乙個整型向量a vector a 10 定義乙個整型向量a,其中有10元素,值隨機 vector a 10,2 定義乙個整型向量a,其中有10個元素,每個值都為2 a.resize 10 將a的大小重新定義為10,值隨...