發表文章

目前顯示的是 1月, 2009的文章

迭代存取的謬誤

昨天寫的兩段愚蠢的Code,可以掉入兩個這樣的陷阱,刀也該拿去再磨磨了。 第一個 #include <vector> using namespace std; int main() { vector<int> v; // .... 寫了某些code 有可能有資料存到v裡頭 .... for (unsigned int i=v.size()-1 ; i>=0 ; --i) v.pop_back(); return 0; } 第二個 #include <list> using namespace std; int main() { list<int> l; for (int i=0 ; i<10 ; ++i) l.push_back(i); // 移除裡面的元素 for (int i=0 ; i<l.size() ; ++i) l.remove(i); return 0; } 第一個程式執行結果理應是無限迴圈,肇因於我在宣告i時使用了unsigned int作為資料型態,而我使用遞減進行for迴圈的迭代,使用unsigned僅僅是想減少warning的出現,沒想到這卻也是敗筆。由於unsinged int 沒有負數,因此當數值為0後,再進行減1的動作會變成最大值(反之,最大值再加1會成為0),因此這個迴圈的條件恆成立。若你認為只有for的條件判斷有問題需要修改,那你就錯了!在for的初始化部份也存在問題,當v.size()為0時,i的起始就因減1而成為最大值,也會造成程式的執行不正確,就算只改了判斷式,程式依然有可能進行錯誤的迭代。 第二個程式則是還沒移除所有的元素就會結束。因為l.size()是即時反應這個list中的元素個數,而我們使用l.remove()後會使l.size()減少,但是i依然會增加,導致我們只會移除list內一半數量。比較好的方法應該改為用while迴圈,並以l.empty()當作條件來判斷是否要結束;不過,若是常常使用vector.size()作為迴圈條件,就會覺得這個迴圈很直覺的是對的,難以察覺臭蟲的存在。