迭代存取的謬誤
昨天寫的兩段愚蠢的Code,可以掉入兩個這樣的陷阱,刀也該拿去再磨磨了。
第一個
第二個
第一個程式執行結果理應是無限迴圈,肇因於我在宣告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()作為迴圈條件,就會覺得這個迴圈很直覺的是對的,難以察覺臭蟲的存在。
第一個
#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()作為迴圈條件,就會覺得這個迴圈很直覺的是對的,難以察覺臭蟲的存在。
留言