2

ベクトルからイテレータを消去したいので、これが現在の状態です。

void function(std::vector <class*> & vector)
{
    std::vector <class*>::iterator it;
    for(it = vector.begin(); iter != vector.end(); ++iter)
        {
            if(it->value == 1)
                vector.erase(it);
        }
    Display(vector);
    return;
}

どうやらこのコードは、イテレータが削除されたときにエラーが発生し、それ以外の場合は正常に機能しているようです。このようなループ内でベクトルを変更することは望ましくない動作である可能性があることはわかっていますが、これを行う必要がある場合、最善の方法は何でしょうか。

ありがとう。

4

3 に答える 3

5
for (it = vector.begin(); it != vector.end(); )
{
    if (it->value == 1)
        it = vector.erase(it);
    else
        ++it;
}

ただし、この場合、実際にstd::remove_ifは適切な述語を使用する必要があります。

于 2012-04-18T19:00:52.383 に答える
4

別のアプローチ:

vector.erase( std::remove_if( vector.begin(), vector.end(), boost::bind( &class::value, _1 ) == 1 ), vector.end() );

boost::bind利用可能であれば、おそらく置き換えることがstd::bindできます。

于 2012-04-18T19:01:06.333 に答える
-1

ベクトルを反復しながらベクトルから消去するのは悪い考えです。濾すだけです。

void function(std::vector <class*> & vector)
{
    std::vector <class*>::iterator from= vector.begin();
    std::vector <class*>::iterator to= from;
    for(; from != vector.end(); ++from)
        {
            if((*from)->value == 1) continue; 
            // it should be (*from) or use boost::ptr_vector
            *(to++)=*from;
        }
    vector.erase( to, vector.end() );
    Display(vector);
    return;
}

これは、Ylisar によるコードとまったく同じ機能です。IMHOこれは、常に何かを削除する場合はベクターに最適ですが、削除が非常にまれな場合(1つのベクター全体に対して)、Benjamin Lindleyバージョンを使用してください。

最適化が何であれ、消去するものがある場合にのみフィルタリングできます。

void function(std::vector <class*> & vector)
{
   std::vector <class*>::iterator to= vector.begin(); 
   for(; to != vector.end(); ++to)
   {
      if((*to)->value == 1) 
      {
         std::vector <class*>::iterator from=to;
         for(++from; from != vector.end(); ++from)
         {
            if((*from)->value == 1) continue;
            *(to++)=*from;
         }
         vector.erase( to, vector.end() );
         break;
      }
    }
    Display(vector);
    return;
}

順序を維持する必要がない場合は、コピーの過熱を最小限に抑えてコピーすることができます。

void function(std::vector <class*> & vector)
{
   std::vector <class*>::iterator to= vector.begin(); 
   std::vector <class*>::iterator from=vector.end();
   if(to == from) return;
   for(;;)
   {
      if((*to)->value == 1) // need skip value from begin
      {
         for( --from; from != to; --from)
         {
            if((*from)->value == 1) continue; // need skip value from end
            *to=*from;
            ++to; // copied, move to next
         }
      } 
      else 
      {
         ++to; //preserved, move to next
      }
      if(to == from) 
      {
         vector.erase( to, vector.end() ); 
         break;
      }
    }
    Display(vector);
    return;
}
于 2012-04-18T19:14:02.873 に答える