順序容器迭代器之鄙見

2022-03-30 05:19:46 字數 2473 閱讀 7198

***眾所周知當使用乙個容器的insert或者erase函式通過迭代器插入或刪除元素"可能"會導致迭代器失效,因此很多建議都是讓我們獲取insert或者erase返回的迭代器,以便用重新獲取新的有效的迭代器進行正確的操作:

view plaincopy to clipboardprint?

iter=vec.insert(iter);   

iter=vec.erase(iter);      

想想究竟為什麼迭代器失效,原因也不難理解。以vector為例,當我們插入乙個元素時它的預分配空間不夠時,它會重新申請一段新空間,將原空間上的元素複製到新的空間上去,然後再把新加入的元素放到新空間的尾部,以滿足vector元素要求連續儲存的目的。而後原空間會被系統撤銷或徵做他用,於是指向原空間的迭代器就成了類似於「懸垂指標」一樣的東西,指向了一片非法區域。如果使用了這樣的迭代器會導致嚴重的執行時錯誤就變得很自然了。這也是許多書上敘述vector在insert操作後「可能導致所有迭代器實效」的原因。但是想到這裡我不禁想到vector的erase操作的敘述是「會導致指向刪除元素和刪除元素之後的迭代器失效」。但是明顯感覺erase帶來失效要比insert來得輕得多。似乎「此失效非彼失效」,想想似乎也是這樣的:erase操作是在原空間上進行的,假設有乙個存有"12345"序列的vector容器原本指向3的迭代器在我刪除2之後無非變成指向4了,我只要注意別用到超過end位置的迭代器不就行了嗎?

說了這麼多似乎可以歸納一下迭代器失效的型別了:

1.由於容器元素整體「遷移」導致存放原容器元素的空間不再有效,從而使得指向原空間的迭代器失效。

2.由於刪除元素使得某些元素次序發生變化使得原本指向某元素的迭代器不再指向希望指向的元素。

對於第一種型別沒什麼好就是的了,原因應該確定如此了。可對於第二種,我寫了如下的**

view plaincopy to clipboardprint?

vectorvec;   

for(int i=0;i<10;i++)   

vec.push_back(i);   

vector::iterator iter =vec.begin()+2;   

vec.erase(iter);//注:這裡真的不建議這麼寫   

cout<<*iter<::iterator it=vec.begin();it!=vec.end();it++)   

cout<<*itfor(int i=0;i<10;i++)   

vec.push_back(i);   

cout<<"capacity:"<::iterator iter =vec.begin()+2;   

vec.insert(iter,100);   

cout<<"capacity:"<::iterator it=vec.begin();it!=vec.end();it++)   

cout<<*it《首先對於vector而言,新增和刪除操作可能使容器的部分或者全部迭代器失效。那為什麼迭代器會失效呢?vector元素在記憶體中是順序儲存,試想:如果當前容器中已經存在了10個元素,現在又要新增乙個元素到容器中,但是記憶體中緊跟在這10個元素後面沒有乙個空閒空間,而vector的元素必須順序儲存一邊索引訪問,所以我們不能在記憶體中隨便找個地方儲存這個元素。於是vector必須重新分配儲存空間,用來存放原來的元素以及新新增的元素:存放在舊儲存空間的元素被複製到新的儲存空間裡,接著插入新的元素,最後撤銷舊的儲存空間。這種情況發生,一定會導致vector容器的所有迭代器都失效。

我們看到實現上述所說的分配和撤銷記憶體空間的方式以實現vector的自增長性,效率是極其低下的。為了使vector容器實現快速的記憶體分配,實際分配的容器會比當前所需的空間多一些,vector容器預留了這些額外的儲存區,用來存放新新增的元素,而不需要每次都重新分配新的儲存空間。你可以從vector裡實現capacity和reserve成員可以看出這種機制。

capacity和size的區別:size是容器當前擁有的元素個數,而capacity則指容器在必須分配新儲存空間之前可以儲存的元素總數。

deque迭代器的失效情況: 在c++primer一書中是這樣限定的: 1.在deque容器首部或者尾部插入元素不會使得任何迭代器失效。 2.在其首部或尾部刪除元素則只會使指向被刪除元素的迭代器失效。 3.在deque容器的任何其他位置的插入和刪除操作將使指向該容器元素的所有迭代器失效。但是:我在vs2005測試發現第一條都不滿足,不知為何?等以後深入stl以後慢慢的領會吧!

只有list的迭代器好像很少情況下會失效。也許就只是在刪除的時候,指向被刪除節點的迭代器會失效吧,其他的還沒有發現。

以下純屬個人猜想,有待考證~

看了上述文章,我個人覺得迭代器應該是按儲存順序有內在編號的,當利用迭代器iterator(假如內建編號為3)插入乙個元素或刪除乙個元素後,迭代器iterator原來的內建編號已經和現在元素的儲存順序不匹配,於是需要語句

iter=vec.insert(iter);   

iter=vec.erase(iter);     

進行重置指向,因為iterator內建編號還是3,所以要將iterator重新指向第三個元素;

容器 迭代器

stl包括 容器 資料結構 迭代器 遍歷資料 演算法 順序容器 vector 向量 list 鍊錶 deque 雙端佇列 關聯容器 set 集合 multist map 對映 multimap 迭代器 類似於指標 用來訪問容器中的單個資料項 迭代器由類iterator來宣告。include incl...

Qt的容器類之容器,迭代器

qt中的容器被分為兩個大類 容器元素是乙個值的,比如qvector,以及容器元 素是乙個 key,value 對的,比如qmap。1 第一大類中,qvector將其所有元素存放在一塊連續的記憶體中。隨機訪問的速度很快,但是插入 刪除操作很慢。qstack是qvector的子類,實現棧的功能。除了具有...

c 容器演算法迭代器初識 容器演算法迭代器

c 容器演算法迭代器初識 容器演算法迭代器 stl中最常用的為迭代器vector,可以理解為陣列,下面我們將學習如何向這個容器 中插入資料 並遍歷這個容器 容器 vector 演算法 for each 迭代器 vector iteator include include include using ...