2

繰り返し処理する一連のオブジェクトがありますが、繰り返し処理中に、これらのオブジェクトの 1 つ (または複数) を削除する必要があると判断する場合があります。

私のコードは次のようになります。

if( ! m_Container.empty() )
    {
        for(  typedefedcontainer::iterator it = m_Container.begin();
              it != m_Container.end(); 
              ++it  )
        {
            if( ! ( SomeFunction( (*it), "test", "TEST!", false ))  )
            {
            // If function returns false, delete object.
                m_Container.erase( it );
                AsyncResponseStore::iterator it = m_asyncResponses.begin();
            }

        }


    }

しかしもちろん、オブジェクトを消去すると、「Map / set iterator not incrementable」というエラーが表示されます。誰かがこれを行うためのより良い方法を提案できますか?

参照: 最初から最後まで反復しているときにマップ要素で erase() を呼び出すとどうなりますか?

4

3 に答える 3

6

コンテナがそれをサポートしている場合(あなたのものはサポートしていないと思いますが、質問のタイトルは一般的なものなので、あなたでない場合は他の人に役立つかもしれません):

struct SomePredicate {
    bool operator()(typedefedcontainer::value_type thing) {
        return ! SomeFunction(thing, "test", "TEST", false);
    }
};

typedefedcontainer::iterator it;
it = std::remove_if(m_Container.begin(), m_Container.end(), SomePredicate());
m_Container.erase(it, m_Container.end());

m_Container には、シーケンスまたは連想コンテナを含む消去範囲メソッドが必要です。ただし、変更可能なイテレータが必要であり、最初にエラーメッセージを読み間違えたことに気付きました.「マップ/イテレータをインクリメントできません」と表示されています。したがって、コンテナはマップまたはセットだと思います。

最後の 3 つは本当に素晴らしいワンライナーになる可能性がありますが、この余白は狭すぎてそれを含めることができないことに注意してください。

また、 SomePredicate には、追加のパラメーターを SomeFunction に格納するためのパラメーターを持つコンストラクターを含めることができます。実際には、それらは定数ではないと思うからです。

boost:bind を使用してファンクターを構築すると、実際には SomePredicate を完全に取り除くことができます。あなたのワンライナーは本当に大規模になります.

[編集: Rob Walker は、私がここで行った仮定と、質問には記載されていないこと、つまり、反復とテストが完了するまですべての消去を延期できるという仮定を、彼の回答で正しく指摘しています。SomeFunction が隠しルート (たとえば、グローバル、または SomeFunction が実際には this のメンバー関数であるため) によって m_Container にアクセスし、その結果がコンテナーの内容に依存する場合、私のコードは質問者のコードと同等ではない可能性があります。しかし、私のコードは「そうしない理由がない限り」デフォルトだと思います。]

于 2008-12-09T16:39:51.433 に答える
6

容器にもよります。リスト コンテナーは、リスト内の次の項目を表す erase メソッドから新しい反復子を返すことにより、列挙中の削除をサポートします。マップはこれをサポートしていません。

map の簡単な方法は、消去したいアイテムを別のリストに蓄積し、マップの処理が終了したらそのリストを繰り返し処理して、マップからアイテムを消去することです。これは、反復が完了するまで削除を延期できることを前提としています。そうでない場合は、削除するたびに反復を再開するしかありません。

于 2008-12-09T16:18:08.920 に答える
0

以下によって修正されました:

for(  typedefedcontainer::iterator it = m_Container.begin();
      it != m_Container.end(); 
        )
{
    if( ! ( SomeFunction( (*it), "test", "TEST!", false ))  )
    {
    // If function returns false, delete object.
        m_Container.erase( it++ );
    }
    else
    { 
        ++i;
    } 

}

要素が削除されると、その要素へのすべてのポインタが無効になります。したがって、it ++を使用することで、それを回避できます。提案を投稿してくれた人たちに感謝します。

于 2008-12-09T16:30:45.400 に答える