zoukankan      html  css  js  c++  java
  • 转载: STL序列式容器中删除元素的方法和陷阱二 .

    2.使用 STL 中通用算法或容器成员函数删除元素的方法

    以上手工编写 for 循环代码删除容器中元素的方法也有一些问题,如果判断条件特别复杂,又有循环判断的话,循环中间又有异常处理的话, ++itVect 的位置就要小心放置了,稍不留意就要出错。所以手工编写代码删除容器中元素的方法不太安全,代码重复,也不够优雅,要注意的地方很多。

    对于这种情况,可以考虑使用 STL 中通用算法 remvoe() 和 remove_if() 帮忙。而 remvoe() 和 remove_if() 这两个算法也有一个问题需要程序员特别小心。 在通用算法中的 remove (包括 remove_if ) 函数,并不真正从容器中删除元素,而是“应被删除的元素”被其后的“未被删除的元素”覆盖。返回值 ForwardIterator 指向经移除后的最后元素的下一位置。如 vector{0,1,2,3,3,4} ,执行 remove() ,希望移除所有值为 3 的元素,结果为 {0,1,2,4,3,4} ,返回值 ForwardIterator 指向第 5 个元素。即:

    0        1        2        3         3       4  移除前

    0        1        2        4         3       4  移除后

    移除值为 3 的元素。移除后 3 被其后的 4 替代,最后两位元素为残余数据。

    例 5 :

    void main() {

           vector<int> vectInt;

           int i;

           for (i = 0; i < 5; i++ ) {

                  vectInt.push_back( i );

                  if ( 3 == i ) {

                         vectInt.push_back( i );

                  }

           }

           remove( vectInt.begin(), vectInt.end(), 3 );

           cout << " after deleted , size = " << vectInt.size() << endl;

           for ( i = 0; i < vectInt.size();; i++ ) {

                  cout << "i = " << i << " , " << vectInt[i] << endl;

           }

    }

    运行结果为:

    after deleted , size = 6 // 从这行可以看出,移除后容器的大小没变

    i = 0 , 0

    i = 1 , 1

    i = 2 , 2

    i = 3 , 4 //  从这行可以看出:“应被删除的元素” 3 被其后的“未被删除的元素” 4 覆盖

    i = 4 , 3

    i = 5 , 4     

    所以要彻底删除还应该把后面的残余数据删除掉,这可以通过调用容器的成员函数 erase() 做到。

    例 6 :

    void main() {

           vector<int> vectInt;

           int i;

           for (i = 0; i < 5; i++ ) {

                  vectInt.push_back( i );

                  if ( 3 == i ) {

                         vectInt.push_back( i );

                  }

           }

           vectInt.erase( remove( vectInt.begin(), vectInt.end(), 3 ), vectInt.end() );

           cout << " after deleted , size = " << vectInt.size() << endl;

           for ( i = 0; i < vectInt.size();; i++ ) {

                  cout << "i = " << i << " , " << vectInt[i] << endl;

           }

    }

    运行结果为:

    after deleted , size = 4 // 从这行可以看出,删除后容器的大小变化了

    i = 0 , 0

    i = 1 , 1

    i = 2 , 2

    i = 3 , 4

    从结果可以看出,所有值为 3 的元素确实被删除了。

    对于 vector 容器存放其他比较复杂的对象,就可以用 remove_if() 加函数对象( Function Object )的方法。

    如:

    例 7 :

    #include <iostream>

    #include <sstream>

    #include <string>

    #include <vector>

    #include <algorithm>

    #include <list>

    using namespace std;

    class CTest {

    public:

           CTest( const string& str, int iPrice ) : m_strName( str ), m_iPrice( iPrice ) { }

          void vPrint() { cout << "name=" << m_strName << " price = " << m_iPrice << endl;

           }

    private:

           string m_strName;

           int   m_iPrice;

           //     由于两个函数对象要访问 CTest 类的 private 成员,所以设为友员。

           friend class CStrFunc;

           friend class CIntFunc;

    };

    //     函数对象,根据 string 比较

    class CStrFunc {

           string m_str;

    public:

           CStrFunc( const string& str ) : m_str( str ) {

           }

           bool operator() ( const CTest& left ) {

                  return ( m_str == left.m_strName ) ? true : false;

           }

    };

    //     函数对象,根据 int 比较

    class CIntFunc {

           int m_iPrice;

    public:

           CIntFunc( int iPrice ) : m_iPrice( iPrice ) {

           }

           bool operator() ( const CTest& left ) {

                  return ( m_iPrice == left.m_iPrice ) ? true : false;

           }

    };

    void main( ) {

     

           vector< CTest > vectTest;

           int i;

           for (  i = 0; i < 5 ; i++ ) {

                  stringstream stream; //       流格式化符,把 int 转化为 string

                  stream << i;

                  string str = stream.str();

                  CTest clTest( str, i );

                  vectTest.push_back( clTest );

           }

          for (  i = 0 ; i < vectTest.size(); i++ )  {

                  vectTest[ i ].vPrint();

           }

           //     删除所有 m_strName = "3" 的元素

           vectTest.erase( remove_if( vectTest.begin(), vectTest.end(), CStrFunc( "3" ) ),

                  vectTest.end() );

           cout << "delete 3 after : " << endl;

          for (  i = 0 ; i < vectTest.size(); i++ )  {

                  vectTest[ i ].vPrint();

           }

           //     删除所有

  • 相关阅读:
    FCC学习笔记(二)
    FCC学习笔记(一)
    jQuery(三)
    jQuery(二)
    jQuery(一)
    JavaScript(九)
    JavaScript(八)
    2-1回归算法
    14-章小结
    13-模型训练及测试
  • 原文地址:https://www.cnblogs.com/kex1n/p/2283672.html
Copyright © 2011-2022 走看看