现在的位置: 首页 > 综合 > 正文

STL Vector 的遍历删除

2018年06月08日 ⁄ 综合 ⁄ 共 1951字 ⁄ 字号 评论关闭

转载自:http://www.cppblog.com/Khan/archive/2009/12/08/102793.html

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 ) );

抱歉!评论已关闭.