C++ vector的用法小結(jié)
c++ vector用法
C++內(nèi)置的數(shù)組支持容器的機(jī)制,但是它不支持容器抽象的語義。要解決此問題我們自己實現(xiàn)這樣的類。在標(biāo)準(zhǔn)C++中,用容器向量(vector)實現(xiàn)。容器向量也是一個類模板。
標(biāo)準(zhǔn)庫vector類型使用需要的頭文件:#include <vector>。vector 是一個類模板。不是一種數(shù)據(jù)類型,vector<int>是一種數(shù)據(jù)類型。Vector的存儲空間是連續(xù)的,list不是連續(xù)存儲的。
一、 定義和初始化
vector< typeName > v1; //默認(rèn)v1為空,故下面的賦值是錯誤的v1[0]=5;
vector<typeName>v2(v1); 或v2=v1;或vector<typeName> v2(v1.begin(), v1.end());//v2是v1的一個副本,若v1.size()>v2.size()則賦值后v2.size()被擴(kuò)充為v1.size()。
vector< typeName > v3(n,i);//v3包含n個值為i的typeName類型元素
vector< typeName > v4(n); //v4含有n個值為0的元素
int a[4]={0,1,2,3,3}; vector<int> v5(a,a+5);//v5的size為5,v5被初始化為a的5個值。后一個指針要指向?qū)⒈豢截惖哪┰氐南乱晃恢谩?br />
vector<int> v6(v5);//v6是v5的拷貝
vector< 類型 > 標(biāo)識符(最大容量,初始所有值);
二、 值初始化
1> 如果沒有指定元素初始化式,標(biāo)準(zhǔn)庫自行提供一個初始化值進(jìn)行值初始化。
2> 如果保存的式含有構(gòu)造函數(shù)的類類型的元素,標(biāo)準(zhǔn)庫使用該類型的構(gòu)造函數(shù)初始化。
3> 如果保存的式?jīng)]有構(gòu)造函數(shù)的類類型的元素,標(biāo)準(zhǔn)庫產(chǎn)生一個帶初始值的對象,使用這個對象進(jìn)行值初始化。
三、vector對象最重要的幾種操作
1. v.push_back(t) 在容器的最后添加一個值為t的數(shù)據(jù),容器的size變大。
另外list有push_front()函數(shù),在前端插入,后面的元素下標(biāo)依次增大。
2. v.size() 返回容器中數(shù)據(jù)的個數(shù),size返回相應(yīng)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的內(nèi)容。
還有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中刪除一個元素后,此位置以后的元素都需要往前移動一個位置,雖然當(dāng)前迭代器位置沒有自動加1,
但是由于后續(xù)元素的順次前移,也就相當(dāng)于迭代器的自動指向下一個位置一樣。
8. v1==v2 判斷v1與v2是否相等。
9. !=、<、<=、>、>= 保持這些操作符慣有含義。
10. vector<typeName>::iterator p=v1.begin( ); p初始值指向v1的第一個元素。*p取所指向元素的值。
對于const vector<typeName>只能用vector<typeName>::const_iterator類型的指針訪問。
11. p=v1.end( ); p指向v1的最后一個元素的下一位置。
12.v.clear() 刪除容器中的所有元素。12.v.clear() 刪除容器中的所有元素。
#include<algorithm>中的泛函算法
搜索算法:find() 、search() 、count() 、find_if() 、search_if() 、count_if()
分類排序:sort() 、merge()
刪除算法:unique() 、remove()
生成和變異:generate() 、fill() 、transformation() 、copy()
關(guān)系算法:equal() 、min() 、max()
sort(v1.begin(),vi.begin()+v1.size/2); 對v1的前半段元素排序
list<char>::iterator pMiddle =find(cList.begin(),cList.end(),'A');找到則返回被查內(nèi)容第一次出現(xiàn)處指針,否則返回end()。
vector< typeName >::size_type x ; vector< typeName >類型的計數(shù),可用于循環(huán)如同for(int i)
初學(xué)C++的程序員可能會認(rèn)為vector的下標(biāo)操作可以添加元素,其實不然:
vector<int> ivec; // empty vector
for (vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec[ix] = ix; // disaster: ivec has no elements
上述程序試圖在ivec中插入10個新元素,元素值依次為0到9的整數(shù)。但是,這里ivec是空的vector對象,而且下標(biāo)只能用于獲取已存在的元素。
這個循環(huán)的正確寫法應(yīng)該是:
for (vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec.push_back(ix); // ok: adds new element with value ix
警告:必須是已存在的元素才能用下標(biāo)操作符進(jìn)行索引。通過下標(biāo)操作進(jìn)行賦值時,不會添加任何元素。僅能對確知已存在的元素進(jìn)行下標(biāo)操作
四、內(nèi)存管理與效率
1.使用reserve()函數(shù)提前設(shè)定容量大小,避免多次容量擴(kuò)充操作導(dǎo)致效率低下。
關(guān)于STL容器,最令人稱贊的特性之一就是是只要不超過它們的最大大小,它們就可以自動增長到足以容納你放進(jìn)去的數(shù)據(jù)。(要知道這個最大值,只要調(diào)用名叫max_size的成員函數(shù)。)對于vector和string,如果需要更多空間,就以類似realloc的思想來增長大小。vector容器支持隨機(jī)訪問,因此為了提高效率,它內(nèi)部使用動態(tài)數(shù)組的方式實現(xiàn)的。在通過 reserve() 來申請?zhí)囟ù笮〉臅r候總是按指數(shù)邊界來增大其內(nèi)部緩沖區(qū)。當(dāng)進(jìn)行insert或push_back等增加元素的操作時,如果此時動態(tài)數(shù)組的內(nèi)存不夠用,就要動態(tài)的重新分配當(dāng)前大小的1.5~2倍的新內(nèi)存區(qū),再把原數(shù)組的內(nèi)容復(fù)制過去。所以,在一般情況下,其訪問速度同一般數(shù)組,只有在重新分配發(fā)生時,其性能才會下降。正如上面的代碼告訴你的那樣。而進(jìn)行pop_back操作時,capacity并不會因為vector容器里的元素減少而有所下降,還會維持操作之前的大小。對于vector容器來說,如果有大量的數(shù)據(jù)需要進(jìn)行push_back,應(yīng)當(dāng)使用reserve()函數(shù)提前設(shè)定其容量大小,否則會出現(xiàn)許多次容量擴(kuò)充操作,導(dǎo)致效率低下。
reserve成員函數(shù)允許你最小化必須進(jìn)行的重新分配的次數(shù),因而可以避免真分配的開銷和迭代器/指針/引用失效。但在我解釋reserve為什么可以那么做之前,讓我簡要介紹有時候令人困惑的四個相關(guān)成員函數(shù)。在標(biāo)準(zhǔn)容器中,只有vector和string提供了所有這些函數(shù)。
(1) size()告訴你容器中有多少元素。它沒有告訴你容器為它容納的元素分配了多少內(nèi)存。
(2) capacity()告訴你容器在它已經(jīng)分配的內(nèi)存中可以容納多少元素。那是容器在那塊內(nèi)存中總共可以容納多少元素,而不是還可以容納多少元素。如果你想知道一個vector或string中有多少沒有被占用的內(nèi)存,你必須從capacity()中減去size()。如果size和capacity返回同樣的值,容器中就沒有剩余空間了,而下一次插入(通過insert或push_back等)會引發(fā)上面的重新分配步驟。
(3) resize(Container::size_type n)強(qiáng)制把容器改為容納n個元素。調(diào)用resize之后,size將會返回n。如果n小于當(dāng)前大小,容器尾部的元素會被銷毀。如果n大于當(dāng)前大小,新默認(rèn)構(gòu)造的元素會添加到容器尾部。如果n大于當(dāng)前容量,在元素加入之前會發(fā)生重新分配。
(4) reserve(Container::size_type n)強(qiáng)制容器把它的容量改為至少n,提供的n不小于當(dāng)前大小。這一般強(qiáng)迫進(jìn)行一次重新分配,因為容量需要增加。(如果n小于當(dāng)前容量,vector忽略它,這個調(diào)用什么都不做,string可能把它的容量減少為size()和n中大的數(shù),但string的大小沒有改變。在我的經(jīng)驗中,使用reserve來從一個string中修整多余容量一般不如使用“交換技巧”,那是條款17的主題。)
這個簡介表示了只要有元素需要插入而且容器的容量不足時就會發(fā)生重新分配(包括它們維護(hù)的原始內(nèi)存分配和回收,對象的拷貝和析構(gòu)和迭代器、指針和引用的失效)。所以,避免重新分配的關(guān)鍵是使用reserve盡快把容器的容量設(shè)置為足夠大,最好在容器被構(gòu)造之后立刻進(jìn)行。
例如,假定你想建立一個容納1-1000值的vector<int>。沒有使用reserve,你可以像這樣來做:
vector<int> v;
for (int i = 1; i <= 1000; ++i) v.push_back(i);
在大多數(shù)STL實現(xiàn)中,這段代碼在循環(huán)過程中將會導(dǎo)致2到10次重新分配。(10這個數(shù)沒什么奇怪的。記住vector在重新分配發(fā)生時一般把容量翻倍,而1000約等于210。)
把代碼改為使用reserve,我們得到這個:
vector<int> v;
v.reserve(1000);
for (int i = 1; i <= 1000; ++i) v.push_back(i);
這在循環(huán)中不會發(fā)生重新分配。
在大小和容量之間的關(guān)系讓我們可以預(yù)言什么時候插入將引起vector或string執(zhí)行重新分配,而且,可以預(yù)言什么時候插入會使指向容器中的迭代器、指針和引用失效。例如,給出這段代碼,
string s;
...
if (s.size() < s.capacity()) {
s.push_back('x');
}
push_back的調(diào)用不會使指向這個string中的迭代器、指針或引用失效,因為string的容量保證大于它的大小。如果不是執(zhí)行push_back,代碼在string的任意位置進(jìn)行一個insert,我們?nèi)匀豢梢员WC在插入期間沒有發(fā)生重新分配,但是,與伴隨string插入時迭代器失效的一般規(guī)則一致,所有從插入位置到string結(jié)尾的迭代器/指針/引用將失效。
回到本條款的主旨,通常有兩情況使用reserve來避免不必要的重新分配。第一個可用的情況是當(dāng)你確切或者大約知道有多少元素將最后出現(xiàn)在容器中。那樣的話,就像上面的vector代碼,你只是提前reserve適當(dāng)數(shù)量的空間。第二種情況是保留你可能需要的最大的空間,然后,一旦你添加完全部數(shù)據(jù),修整掉任何多余的容量。
2.使用“交換技巧”來修整vector過??臻g/內(nèi)存
有一種方法來把它從曾經(jīng)最大的容量減少到它現(xiàn)在需要的容量。這樣減少容量的方法常常被稱為“收縮到合適(shrink to fit)”。該方法只需一條語句:vector<int>(ivec).swap(ivec);
表達(dá)式vector<int>(ivec)建立一個臨時vector,它是ivec的一份拷貝:vector的拷貝構(gòu)造函數(shù)做了這個工作。但是,vector的拷貝構(gòu)造函數(shù)只分配拷貝的元素需要的內(nèi)存,所以這個臨時vector沒有多余的容量。然后我們讓臨時vector和ivec交換數(shù)據(jù),這時我們完成了,ivec只有臨時變量的修整過的容量,而這個臨時變量則持有了曾經(jīng)在ivec中的沒用到的過剩容量。在這里(這個語句結(jié)尾),臨時vector被銷毀,因此釋放了以前ivec使用的內(nèi)存,收縮到合適。
3.用swap方法強(qiáng)行釋放STL Vector所占內(nèi)存
template < class T> void ClearVector( vector<T>& v )
{
vector<T>vtTemp;
vtTemp.swap( v );
}
如
vector<int> v ;
nums.push_back(1);
nums.push_back(3);
nums.push_back(2);
nums.push_back(4);
vector<int>().swap(v);
/* 或者v.swap(vector<int>()); */
/*或者{ std::vector<int> tmp = v; v.swap(tmp); }; //加大括號{ }是讓tmp退出{ }時自動析構(gòu)*/
五、Vector 內(nèi)存管理成員函數(shù)的行為測試
C++ STL的vector使用非常廣泛,但是對其內(nèi)存的管理模型一直有多種猜測,下面用實例代碼測試來了解其內(nèi)存管理方式,測試代碼如下:
#include <iostream> #include <vector> using namespace std; int main() { vector<int> iVec; cout << "容器 大小為: " << iVec.size() << endl; cout << "容器 容量為: " << iVec.capacity() << endl; //1個元素, 容器容量為1 iVec.push_back(1); cout << "容器 大小為: " << iVec.size() << endl; cout << "容器 容量為: " << iVec.capacity() << endl; //2個元素, 容器容量為2 iVec.push_back(2); cout << "容器 大小為: " << iVec.size() << endl; cout << "容器 容量為: " << iVec.capacity() << endl; //3個元素, 容器容量為4 iVec.push_back(3); cout << "容器 大小為: " << iVec.size() << endl; cout << "容器 容量為: " << iVec.capacity() << endl; //4個元素, 容器容量為4 iVec.push_back(4); iVec.push_back(5); cout << "容器 大小為: " << iVec.size() << endl; cout << "容器 容量為: " << iVec.capacity() << endl; //5個元素, 容器容量為8 iVec.push_back(6); cout << "容器 大小為: " << iVec.size() << endl; cout << "容器 容量為: " << iVec.capacity() << endl; //6個元素, 容器容量為8 iVec.push_back(7); cout << "容器 大小為: " << iVec.size() << endl; cout << "容器 容量為: " << iVec.capacity() << endl; //7個元素, 容器容量為8 iVec.push_back(8); cout << "容器 大小為: " << iVec.size() << endl; cout << "容器 容量為: " << iVec.capacity() << endl; //8個元素, 容器容量為8 iVec.push_back(9); cout << "容器 大小為: " << iVec.size() << endl; cout << "容器 容量為: " << iVec.capacity() << endl; //9個元素, 容器容量為16 /* vs2005/8 容量增長不是翻倍的,如 9個元素 容量9 10個元素 容量13 */ /* 測試effective stl中的特殊的交換 swap() */ cout << "當(dāng)前vector 的大小為: " << iVec.size() << endl; cout << "當(dāng)前vector 的容量為: " << iVec.capacity() << endl; vector<int>(iVec).swap(iVec); cout << "臨時的vector<int>對象 的大小為: " << (vector<int>(iVec)).size() << endl; cout << "臨時的vector<int>對象 的容量為: " << (vector<int>(iVec)).capacity() << endl; cout << "交換后,當(dāng)前vector 的大小為: " << iVec.size() << endl; cout << "交換后,當(dāng)前vector 的容量為: " << iVec.capacity() << endl; return 0; }
六、vector的其他成員函數(shù)
c.assign(beg,end)
將[beg; end)區(qū)間中的數(shù)據(jù)賦值給c。
c.assign(n,elem)
將n個elem的拷貝賦值給c。
c.at(idx)
傳回索引idx所指的數(shù)據(jù),如果idx越界,拋出out_of_range。
c.back()
傳回最后一個數(shù)據(jù),不檢查這個數(shù)據(jù)是否存在。
c.front()
傳回地一個數(shù)據(jù)。
get_allocator
使用構(gòu)造函數(shù)返回一個拷貝。
c.rbegin()
傳回一個逆向隊列的第一個數(shù)據(jù)。
c.rend()
傳回一個逆向隊列的最后一個數(shù)據(jù)的下一個位置。
c.~ vector <Elem>()
銷毀所有數(shù)據(jù),釋放內(nèi)存。
以下是其它網(wǎng)友的補(bǔ)充:
1 、基本操作
(1)頭文件#include<vector>.
(2)創(chuàng)建vector對象,vector<int> vec;
(3)尾部插入數(shù)字:vec.push_back(a);
(4)使用下標(biāo)訪問元素,cout<<vec[0]<<endl;記住下標(biāo)是從0開始的。
(5)使用迭代器訪問元素.
vector<int>::iterator it; for(it=vec.begin();it!=vec.end();it++) cout<<*it<<endl;
(6)插入元素: vec.insert(vec.begin()+i,a);在第i+1個元素前面插入a;
(7)刪除元素: vec.erase(vec.begin()+2);刪除第3個元素
vec.erase(vec.begin()+i,vec.end()+j);刪除區(qū)間[i,j-1];區(qū)間從0開始
(8)向量大小:vec.size();
(9)清空:vec.clear();
2、vector的元素不僅僅可以使int,double,string,還可以是結(jié)構(gòu)體,但是要注意:結(jié)構(gòu)體要定義為全局的,否則會出錯。下面是一段簡短的程序代碼:
#include<stdio.h> #include<algorithm> #include<vector> #include<iostream> using namespace std; typedef struct rect { int id; int length; int width; //對于向量元素是結(jié)構(gòu)體的,可在結(jié)構(gòu)體內(nèi)部定義比較函數(shù),下面按照id,length,width升序排序。 bool operator< (const rect &a) const { if(id!=a.id) return id<a.id; else { if(length!=a.length) return length<a.length; else return width<a.width; } } }Rect; int main() { vector<Rect> vec; Rect rect; rect.id=1; rect.length=2; rect.width=3; vec.push_back(rect); vector<Rect>::iterator it=vec.begin(); cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl; return 0; }
3 算法
(1) 使用reverse將元素翻轉(zhuǎn):需要頭文件#include<algorithm>
reverse(vec.begin(),vec.end());將元素翻轉(zhuǎn)(在vector中,如果一個函數(shù)中需要兩個迭代器,
一般后一個都不包含.)
(2)使用sort排序:需要頭文件#include<algorithm>,
sort(vec.begin(),vec.end());(默認(rèn)是按升序排列,即從小到大).
可以通過重寫排序比較函數(shù)按照降序比較,如下:
定義排序比較函數(shù):
bool Comp(const int &a,const int &b)
{
return a>b;
}
調(diào)用時:sort(vec.begin(),vec.end(),Comp),這樣就降序排序。
上一篇:應(yīng)用程序操作NorFlash示例代碼分享(norflash接口使用方法)
欄 目:C語言
本文標(biāo)題:C++ vector的用法小結(jié)
本文地址:http://mengdiqiu.com.cn/a1/Cyuyan/3861.html
您可能感興趣的文章
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)式函數(shù)庫
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對數(shù)怎么表達(dá)
- 04-02c語言沒有round函數(shù) round c語言
- 04-02C語言中怎么打出三角函數(shù) c語言中怎么打出三角函數(shù)的值
- 01-10c語言求1+2+...+n的解決方法
- 01-10求子數(shù)組最大和的解決方法詳解
- 01-10深入理解約瑟夫環(huán)的數(shù)學(xué)優(yōu)化方法
- 01-10深入二叉樹兩個結(jié)點的最低共同父結(jié)點的詳解
- 01-10數(shù)據(jù)結(jié)構(gòu)課程設(shè)計- 解析最少換車次數(shù)的問題詳解
- 01-10c語言 跳臺階問題的解決方法


閱讀排行
本欄相關(guān)
- 04-02c語言函數(shù)調(diào)用后清空內(nèi)存 c語言調(diào)用
- 04-02func函數(shù)+在C語言 func函數(shù)在c語言中
- 04-02c語言的正則匹配函數(shù) c語言正則表達(dá)
- 04-02c語言用函數(shù)寫分段 用c語言表示分段
- 04-02c語言中對數(shù)函數(shù)的表達(dá)式 c語言中對
- 04-02c語言編寫函數(shù)冒泡排序 c語言冒泡排
- 04-02c語言沒有round函數(shù) round c語言
- 04-02c語言分段函數(shù)怎么求 用c語言求分段
- 04-02C語言中怎么打出三角函數(shù) c語言中怎
- 04-02c語言調(diào)用函數(shù)求fibo C語言調(diào)用函數(shù)求
隨機(jī)閱讀
- 01-10delphi制作wav文件的方法
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改
- 04-02jquery與jsp,用jquery
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10SublimeText編譯C開發(fā)環(huán)境設(shè)置
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10C#中split用法實例總結(jié)
- 01-11ajax實現(xiàn)頁面的局部加載