C++Primer筆記之順序容器的使用詳解
順序容器,它將單一類型元素聚集起來成為容器,然后根據(jù)位置來存儲和訪問這些元素,這就是順序容器。標(biāo)準(zhǔn)庫里定義了三種類型:vector(支持快速隨機(jī)訪問)、list(支持快速插入、刪除)、deque(雙端隊(duì)列)容器只定義了少量操作,大多數(shù)額外的操作由算法庫提供。容器內(nèi)元素的類型約束;1、元素類型必須支持賦值運(yùn)算;2、元素類型的對象必須可以復(fù)制。這是容器元素類型的最低要求,如果想支持一些其他特殊要求,則必須具備相關(guān)的性質(zhì)。
可以定義容器的容器vector< vector<int> > lines;//必須使用"> >"中間的空格,否則會出現(xiàn)變異錯誤
迭代器運(yùn)算:
關(guān)系操作符只適用于vector和deque容器,它們可以根據(jù)元素位置直接有效地訪問指定的容器元素。而list容器的迭代器既不支持算術(shù)運(yùn)算(加法或者減法),也不支持關(guān)系運(yùn)算(<=,<,>=,>),它只提供前置和后置的自增、自減運(yùn)算以及相等(不等)運(yùn)算。
迭代器范圍:
c++使用一對迭代器標(biāo)記迭代器范圍,通常命名為first和last或beg和end。該范圍內(nèi)的元素包括迭代器first指向的元素,以及從first開始一直到迭代器last指向的位置之前的所有元素,此類元素范圍稱為左閉合區(qū)間[first,last)。
順序容器的操作:
在容器中添加元素;在容器中刪除元素;設(shè)置容器大??;獲取容器內(nèi)的第一個和最后一個元素。對于begin()、end()、rbegin()、 rend()四個操作,均有const版本。如果容器時const,則其返回類型要加上const_前綴。c.push_back(t) 在容器c的尾部添加值為t的元素,返回void類型。c.push_front(t) 在容器c的前端添加值為t的元素,返回void類型。但是只有l(wèi)ist和deque具有這樣的性質(zhì)。
//容器的順序遍歷
vector<int>::reverse_iterator iterReverse=vect.rbegin();//定義反向迭代器while(iterReverse!=vect.rend())
{
cout<<*iterReverse<<endl;
iterReverse++;
}
vector<int>::iterator iter = vect.begin();//定義正向迭代器
while(iter!=vect.end())
{
cout<<*iter<<endl;
iter++;
}
在容器中的指定位置添加元素:使用insert函數(shù):由于迭代器可能指向超出容器末端的下一位置沒這事一個不存在的元素,因此insert函數(shù)是在其指向位置之前而非其后插入元素。mylist.insert(iter,element);
//獲取中心位置迭代器,需要注意的list不允許如下的迭代器的加法
vector<int>::iterator middle=vectCpy.begin()+vect.size()/2;
vectCpy.insert(middle,1001);//在中間位置添加一個元素
插入一段元素:
vectCpy.insert(vectCpy.begin(),10,9);//在第一個元素后面添加10個初值為9的元素
int num[3]={555,666,777};
vectCpy.insert(vectCpy.end(),num,num+3);//在vectCpy后面加入一段來自num數(shù)組里的元素
vectCpy.insert(vectCpy.end(),vect.begin(),vect.end());//在vectCpy后加入一段來自迭代器對間的元素
需要注意的是,添加元素可能會導(dǎo)致某些或全部迭代器失效,假設(shè)所有迭代器失效是最安全的做法。不要存儲end操作返回的迭代器,為了避免存儲end迭代器,可以在每次做完插入運(yùn)算重新計(jì)算end迭代器值。
關(guān)鍵概念:容器元素都是副本在容器中添加元素時,系統(tǒng)是將元素值復(fù)制到容器里。類似的,使用一段元素初始化新容器時,新容器存放的事原始元素的副本。本復(fù)制的原始值與新容器中的元素各不相干,此后,容器內(nèi)元素值發(fā)生變化時,被復(fù)制的原值不會受到影響,反之亦然。
容器的比較:
比較的容器必須具有相同的容器類型,而且其元素類型也必須相同。容器的比較式基于容器內(nèi)元素的比較。兩個容器具有相同的長度而且所有的元素都相等,那么這兩個容器就相等。如果兩個容器長度不相等,但較短的容器中所有元素都等于較長容器中對應(yīng)的元素,則稱較短的容器小于另一個容器。如果兩個容器都是對方的初始子序列,則它們的比較結(jié)果取決于所比較的第一個不相等的元素。
vector<int> vect;
vect.push_back(1);
vect.push_back(2);
vect.push_back(3);
vector<int> vectCpy(vect);
if(vectCpy==vect) cout<<"Equal"<<endl;
else cout<<"Not Equal"<<endl;
容器大小的操作:
容器類型提供resize函數(shù)來改變?nèi)萜魉脑貍€數(shù)。如果當(dāng)前的容器長度大于新的長度值,則該容器后部的元素會被刪除,如果當(dāng)前的容器長度小于新的長度值,則系統(tǒng)會在該容器后部添加新元素。resize操作可能會使迭代器失效。例子:
list<int> ilist(10,2);//10個元素容器,初始值均為2
ilist.resize(15);//在原有基礎(chǔ)上,再后面添加5個元素,初始值為0
ilist.resize(25,-1);//在上行的基礎(chǔ)上,再后面再添加10個元素,值為-1
ilist.resize(5);//在ilist的后部刪除20個元素
訪問元素:
如果容器非空,那么容器類型的front和back成員將返回容器內(nèi)第一個或最后一個元素的引用
int &ref=vect.front();//front和back返回容器內(nèi)第一個或最后一個元素的引用
ref=1000001;//改變引用的元素,vect內(nèi)元素的值也會改變
cout<<vect[0]<<" "<<vect.at(1)<<endl;//只適用于vector和deque,如果給出的下標(biāo)無效,則會發(fā)生outOfRange的異常
刪除元素:
pop_front和pop_back函數(shù)用于刪除容器內(nèi)的第一個和最后一個元素。
刪除一個或者一段元素更通用的方法是用erase操作,有兩個版本:刪除由一個迭代器指向的單個元素,或刪除由一對迭代器標(biāo)記的一段元素。erase返回一個迭代器,它指向被刪除元素或元素段后面的元素。通常,必須在容器中查找要刪除的元素后,才使用erase操作。尋找一個指定元素最簡單的方法,是使用標(biāo)準(zhǔn)庫中的find方法。必須包含頭文件algorithm.h
#include<algorithm>
list<int>::iterator searchIter= find(mylist.begin(),mylist.end(),1233);
if(searchIter!=mylist.end())//有可能找不到
{
mylist.erase(searchIter);
}
刪除容器內(nèi)所有元素:mylist.clear()或者mylist.erase(mylist.begin(),mylist.end());
容器的選用:
vector和deque容器提供了對元素的快速隨機(jī)訪問,但付出的代價(jià)是,在容器的任意位置插入或刪除元素,比在容器尾部插入和刪除元素的開銷更大。list類型在任何位置都能快速插入和刪除,但付出的代價(jià)是元素的隨機(jī)訪問開銷較大。其原因就是在內(nèi)部實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)中,一個是在內(nèi)存中順序地址分批的,而另一個是在類似鏈表的方式,隨機(jī)地址分配的,所以導(dǎo)致性質(zhì)的不同。
相關(guān)文章
淺析Boost智能指針:scoped_ptr shared_ptr weak_ptr
雖然通過弱引用指針可以有效的解除循環(huán)引用,但這種方式必須在程序員能預(yù)見會出現(xiàn)循環(huán)引用的情況下才能使用,也可以是說這個僅僅是一種編譯期的解決方案,如果程序在運(yùn)行過程中出現(xiàn)了循環(huán)引用,還是會造成內(nèi)存泄漏的2013-09-09C++調(diào)用Python基礎(chǔ)功能實(shí)例詳解
c++調(diào)用Python首先安裝Python,本文以win7為例,給大家詳細(xì)介紹C++調(diào)用Python基礎(chǔ)功能,需要的朋友參考下吧2017-04-04使用C++11實(shí)現(xiàn)Android系統(tǒng)的Handler機(jī)制
這篇文章主要介紹了使用C++11實(shí)現(xiàn)Android系統(tǒng)的Handler機(jī)制,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04C++string中的insert()插入函數(shù)詳解
這篇文章主要介紹了C++string中的insert()插入函數(shù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03Objective-C中常用的結(jié)構(gòu)體NSRange,NSPoint,NSSize(CGSize),NSRect實(shí)例分析
這篇文章主要介紹了Objective-C中常用的結(jié)構(gòu)體NSRange,NSPoint,NSSize(CGSize),NSRect實(shí)例分析,有助于更加直觀的理解Object-C常用的結(jié)構(gòu)體,需要的朋友可以參考下2014-07-07