先看下面的例子:
vector 的元素刪除
話頭從 container 的元素刪除說起。jyhuang 觀察到「如果 vector 或 list
的最後乙個元素符合刪除條件,程式會有問題」。他給我這樣乙個片段:
template
void print_elements(t elem)
void (*pfi)(int) = print_elements; // 函式指標,做為 function object 用
...int ia[7] = ;
vectorivec(ia, ia+7);
for_each(ivec.begin(), ivec.end(), pfi); // 0 1 2 3 4 5 6
for (vector::iterator it = ivec.begin(); it != ivec.end(); it++)
for_each(ivec.begin(), ivec.end(), pfi); // 0 2 4 6 正確!
如果把 array 和 vector 的初值改為:
int ia[8] = ;
vectorivec(ia, ia+8);
則上述程式會當掉。
●i don't think so...
我不相信 stl 會有這麼差勁的表現。所以多做了幾次測試如下。
(1) 把 array 和 vector 的初值改為:
int ia[7] = ;
vectorivec(ia, ia+7);
程式結果為 0 2 4 7。結果不對,但不會當掉。
(2) 把 array 和 vector 的初值改為:
int ia[7] = ;
vectorivec(ia, ia+7);
程式結果為 0 3 7 7。錯得離譜,但不會當掉。
(3) 把 array 和 vector 的初值改為:
int ia[7] = ;
vectorivec(ia, ia+7);
程式執行時會當掉。
我於是多做了一些觀察,然後知道,上述這些動作根本上是完全
不對的。第乙個 sample 之執行結果正確,完全是湊巧。
問題不在「最後乙個元素是否符合刪除條件」,而在對 iterator
特性的認識。當我們做了 ivec.erase(it) 動作,vector 便動態
減縮了乙個元素(邏輯上,後繼元素向前遞補),而 it 不變。
之後 for 迴圈的第三部份述句要求 it++,造成 it 跳過了乙個元素...。
看例項:
(1) 初值為
第一次迭代,發現是偶數: ★ 以下以 e 表示 end()
0 1 2 3 4 5 6 e
^第二次迭代,發現是奇數:
0 1 2 3 4 5 6 e
^於是將 '1' 刪除,vector 變成:
0 2 3 4 5 6 e
^第三次迭代,發現是奇數(這時已發生錯誤,因為 '2' 被跳過,沒有檢查):
0 2 3 4 5 6 e
^於是將 '3' 刪除,vector 變成:
0 2 4 5 6 e
^第四次迭代,發現是奇數(這時已發生錯誤,因為 '4' 被跳過,沒有檢查):
0 2 4 5 6 e
^於是將 '5' 刪除,vector 變成:
0 2 4 6 e
^第五次迭代,發現 it == vec.end(),於是跳離迴圈:
0 2 4 6 e
^此時 vector 剩餘 0 2 4 6,陰錯陽差地與正確結果吻合。
(2) 初值為
第一次迭代,發現是偶數: ★ 以下以 e 表示 end()
0 2 4 6 0 4 7 e
^第二次迭代,發現是偶數:
0 2 4 6 0 4 7 e
^第三次迭代,發現是偶數:
0 2 4 6 0 4 7 e
^第四次迭代,發現是偶數:
0 2 4 6 0 4 7 e
^第五次迭代,發現是偶數:
0 2 4 6 0 4 7 e
^第六次迭代,發現是偶數:
0 2 4 6 0 4 7 e
^第七次迭代,發現是奇數:
0 2 4 6 0 4 7 e
^於是將 '7' 刪除,vector 變成:
0 2 4 6 0 4 e
^第八次迭代,it 越過了 end(),造成越界錯誤。迴圈何時結束,未可知也:
0 2 4 6 0 4 e ? ? ? ? ? ?
^我的結論:
iterator 只適用於在「不更動 container 布局」的條件下,對 container 做巡訪動作。否則,對 iterator 的取值行為,直觀下極易誤用。
原創**:
迭代器的使用
參考 stl中的迭代器有五種型別,不同的容器可支援不同的迭代器 1.vector,支援隨機迭代器 include include include using namespace std int main cout endl cout endl vector iterator iter1 charve...
迭代器的使用
迭代器 iterator 有時又稱游標 cursor 是程式設計的軟體設計模式,他是專門為訪問容器而設計的一種資料結構,他實際是對訪問容器這一操作進行了封裝。也有一種說法是迭代器是指標的封裝。和智慧型指標有點相似。迭代器是一種物件,他用來遍歷標準模板庫容器中的部分或全部元素,每個迭代器物件代表容器中...
使用迭代器
建立迭代器最常用的方法是對 ienumerable 介面實現 getenumerator 方法,例如 c 複製 public system.collections.ienumerator getenumerator getenumerator 方法的存在使得型別成為可列舉的型別,並允許使用 fore...