2009年1月9日 星期五

[C++]常犯的for迴圈邏輯錯誤

最近錯了兩次,除錯浪費不少時間,記一下好了。

剛學 C++ 時,都是用 int 做 for 迴圈的變數檢索陣列,後來才改用 size_t 。當我們需要反方向檢索陣列時,如下例:

const size_t len=5;
int d[len]={1, 2, 3, 4, 5};
for (size_t i=len-1; i>=0; --i) {
    cout << d[i];
}

這樣在 compile 時沒問題,但迴圈很可能會發生「跑不完」的情形。

為什麼?因為當 i=0 跑完迴圈最後一次,再減 1 時,並不是 -1 ,而是 size_t 型別的最大值。於是 i 仍舊大於 0 ,迴圈就會繼續檢索超出陣列範圍的記憶體了。

變數 i 用 int 型別不好嗎?不是不好, compile 會有 warning ,誰知道會不會有什麼邏輯錯誤出現。那要怎麼解決呢?程式改寫如下:

const size_t len=5;
int d[len]={1, 2, 3, 4, 5};
for (size_t i=len; i>0; --i) {
    cout << d[i-1];
}

這樣寫,雖然每次在迴圈裡要多做一次 i-1 ,但是保證不會出現邏輯錯誤。

如果是 STL container 要反方向檢索 container 的內容,則是應該用 reverse_iterator 這個包裝過的反向 iterator 。雖然會多寫一點程式碼 ( 先型別名稱就比 size_t 長多了 ) ,但是保證不會出錯。

1 則留言:

  1. 用 iterator 好像是最保險的,
    size_t 那個風險似乎也不小,
    我的話可能還是用 int 吧 :D

    回覆刪除