眾所周知當使用乙個容器的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?
vector vec;
for(int i=0;i<10;i++)
vec.push_back(i);
vector::iterator iter =vec.begin()+2;
vec.erase(iter);//注:這裡真的不建議這麼寫
cout<< *iter << endl;
for(vector::iterator it=vec.begin();it!=vec.end();it++)
cout<<*it<< endl;
按照我的猜測儘管我在注釋的位置的寫法很「危險」,但是我並未涉及到上面總結第一種失效型別的範疇。程式應該還是會如預期的一樣刪除在vec[2]位置上的2然後輸出前移到vec[2]位置上的3,並輸出0到10不含2的所有數字,於是vs2008的c++環境下執行一下,竟然乙個是個無情的「紅叉」。按道理說這種寫法是絕對不對出現嚴重的執行時錯誤的,難道是猜測得不對嗎?
當時被這樣的疑問困擾了幾天,有一天突然想起乙個關於容器迭代器作引數的例子,在vs2008下執行不了,但是在vc6.0下卻可以,有人說是因為08採用了更為嚴格的型別檢測機制。於是將上面的**放到6.0裡,果然得到了預期的效果,看來系統果然是這麼處理的。至於08為什麼不可以,現在我只能認為是採用了更加安全的檢查機制。使得第二種型別的失效後果同樣「不可饒恕」。
這樣我就又想到假如insert元素時原空間夠用的話,是不是也不會產生第一類失效而產生第二類失效呢?
view plaincopy to clipboardprint?
vector vec;
for(int i=0;i<10;i++)
vec.push_back(i);
cout<<」capacity:」<< vec.capacity()<< endl;//檢視預分配空間大小
vector::iterator iter =vec.begin()+2;
vec.insert(iter,100);
cout<<」capacity:」<< vec.capacity()<< endl;
cout<<*iter<< endl;
for(vector::iterator it=vec.begin();it!=vec.end();it++)
cout<<*it<< endl;
同樣在vc6.0下,證明了假設是對的。但是上面的種種做法只是為了幫助我理解迭代器實效的原因,建議使用insert和erase操作時還是像許多書中介紹的如第一段**那樣的寫法,這是一種好的且安全的習慣。總之一句話去相信「insert和erase操作後所有的迭代器都會失效」
**這裡
C 迭代器失效
眾所周知當使用乙個容器的insert或者erase函式通過迭代器插入或刪除元素 可能 會導致迭代器失效,因此很多建議都是讓我們獲取insert或者erase返回的迭代器,以便用重新獲取新的有效的迭代器進行正確的操作 view plaincopy to clipboardprint?iter vec....
C 迭代器失效
原文 眾所周知當使用乙個容器的insert或者erase函式通過迭代器插入或刪除元素 可能 會導致迭代器失效,因此很多建議都是讓我們獲取insert或者erase返回的迭代器,以便用重新獲取新的有效的迭代器進行正確的操作 view plaincopy to clipboardprint?iter v...
C 迭代器失效
原文 眾所周知當使用乙個容器的insert或者erase函式通過迭代器插入或刪除元素 可能 會導致迭代器失效,因此很多建議都是讓我們獲取insert或者erase返回的迭代器,以便用重新獲取新的有效的迭代器進行正確的操作 view plaincopy to clipboardprint?iter v...