1. 程式人生 > >STL Vector 的遍歷刪除

STL Vector 的遍歷刪除

Vector 其實就類似動態陣列. 事先分配好一定量的記憶體. 當需要的記憶體值大於某個閥值. 就重新申請記憶體. 重新分配. 當小於某個閥值, 也會導致重新分配.(自動收縮部分, stl沒有明確規定, 有些庫實現了)

正確: code1
      vector<string> vecFiles;
      vector<string>::iterator  it_pos;
      //@todo 已下載檔案過濾
      for (it_pos = vecFiles.begin(); it_pos != vecFiles.end(); ) { 
        string strTmp = *it_pos;


        if( objDownHis.checkHisList( strTmp.c_str() ) ){ //判斷是否已下載過, 已下載則從列表刪除
          g_Log << TIME << "file:[" << *it_pos << "] found "<< END; //
          vecFiles.erase(it_pos++);
        }else 
          it_pos++;
      }


正確: code2
      vector<string> vecFiles;
      vector<string>::iterator  it_pos;

      //@todo 已下載檔案過濾
      for (it_pos = vecFiles.begin(); it_pos != vecFiles.end(); ) {  
        string strTmp = *it_pos;
        if( objDownHis.checkHisList( strTmp.c_str() ) ){ //判斷是否已下載過, 已下載則從列表刪除
          g_Log << TIME << "file:[" << *it_pos << "] found "<< END; //
          it_pos = vecFiles.erase(it_pos);

        }else
          it_pos++;
      }

錯誤: code3
      vector<string> vecFiles;
      vector<string>::iterator  it_pos;
      //@todo 已下載檔案過濾
      for (it_pos = vecFiles.begin(); it_pos != vecFiles.end(); it_pos++) {  
        string strTmp = *it_pos;
        if( objDownHis.checkHisList( strTmp.c_str() ) ){ //判斷是否已下載過, 已下載則從列表刪除
          g_Log << TIME << "file:[" << *it_pos << "] found "<< END; //
          vecFiles.erase(it_pos);
        }
      }


code3 錯誤的原因為, vecFiles.erase(it_pos); 當前的it_pos已經被刪除了, 再下一次迴圈的時候 it_pos++, 訪問非法記憶體..

然後回過頭來看code1, vecFiles.erase(it_pos++); 在當前的it_pos已經被刪除的時候, it_pos已經指向下一個位置了. 雖然這裡邏輯上是錯誤的. 但是利用c語法的特性產生了一個正確的結果, 算是一個技巧. 不算是一門技術.

code2, it_pos = vecFiles.erase(it_pos); erase刪除的時候, 也返回了下一個指標的位置,我們將這個位置保留了, 所以這種做法也是正確的.


另外一個移植性比較好的做法是remove_if 和一個仿函式.

仿函式可以是:
struct check {
    check( Object * objDownHis ) : m_obj( objDownHis ) {}
    check( const check & c ) : m_obj( c.m_obj ) {}

    bool operator()(const string & s) const {
       if ( m_obj->checkHisList( s.c_str() ) {
            g_Log .........
            return true;
       }
       return false;
    }
    Object * m_obj;
};

vecFiles.erase( std::remove_if( vecFile.begin(), vecFile.end(), check( &objDownHis ) );


鳴謝p大, lancey, jackz 排名不分先後.. 全按交流時間順序...