19


11

なぜこのベクトル反復子はインクリメントできないのですか?

ベクターのコンテンツを削除しようとしていますが、エラーが発生しています-ベクターの反復子はインクリメントできません。なぜですか?

これは私のデストラクタです:

City::~City()
{
    vector ::iterator deleteIterator;
    for (deleteIterator = m_basesVector.begin() ; deleteIterator != m_basesVector.end() ; deleteIterator++)
        m_basesVector.erase(deleteIterator);
}

ありがとう。

8 Answer


44


`erase`はイテレータを無効にします。 これ以上使用できません。 幸いなことに、使用できるイテレータが返されます。

vector ::iterator deleteIterator = m_basesVector.begin();
while (deleteIterator != m_basesVector.end()) {
    deleteIterator = m_basesVector.erase(deleteIterator);
}

Or:

m_basesVector.clear();

ベクター内のポインターによって参照されるメモリを解放する責任がありますか? それが繰り返しの理由である場合(そして実際のプログラムには表示されていないより多くのコードがあり、ループ内のオブジェクトを解放します)、ベクトルの先頭からの消去は遅い操作であることに注意してください。各ステップで、ベクトルのすべての要素を1つ下にシフトする必要があるためです。 より良いのはベクターをループしてすべてを解放することです(その後、ベクターが破棄されるオブジェクトのメンバーである場合、マイクはそれを必要としないが、ベクターを「clear()」する)。


11


問題は、erase()関数の使用中にイテレータを使用しようとしていることです。 erase()、push_back()、insert()、およびその他の変更関数は、STLの反復子を無効にします。

clear()関数を使用するだけです:

City::~City()
{
    m_basesVector.clear();
}


3


ベクター内のデータを解放しようとしている場合、これを実行します。

for (std::vector::iterator it = v.begin(), e = b.end(); it != e; ++it)
    delete *it;


2


これを投稿すると、他の誰かがこの問題を抱えており、なぜここで機能していないのか疑問に思って、実際の解決策/説明があります。

@Steve Jessop-あなたのコードには欠陥があり、ここにも書かれています…​ (問題が承認され次第、元の投稿で修正されるように、彼の投稿を編集して問題を修正しました)

無限ループを作成して新しい問題を作成するときに、これが問題の「解決策」であることがわかりません。whileループ内にdeleteIterator ++があり、実際にベクトルの最後に到達する必要があります。

また、私はこの問題に遭遇し、私の解決策は、イテレータが最後に等しいかどうか、またはベクトルサイズが0でイテレータをインクリメントしようとする前に中断するかどうかをチェックするwhileループ内にありました。

Ex.

    std::vector::iterator Rank_IT = CurrentPlayers.begin();

    while ( Rank_IT != CurrentPlayers.end() )
    {
        RankPlayer* SelPlayer = (*Rank_IT);

        if( strstr( SelPlayer->GamerTag, this->GamerTag ) != NULL )
        {

            delete[] SelPlayer->PlayerData;
            delete[] SelPlayer;
            Rank_IT = CurrentPlayers.erase( Rank_IT );
        }

        if( Rank_IT == CurrentPlayers.end() || CurrentPlayers.size() == 0 )
        {
            break;
        }
            ++Rank_IT;
    }


2


これは上記の元の問題とは関係ありませんが、エラーのGoogle検索でこのページに移動するため、ここに投稿して誰でも見ることができるようにします。

最近、このエラーメッセージに遭遇し、すべてのコード行がチェックアウトされました(「消去」などはありませんでした。ベクトルは単に読み取られました)。

最終的に、ネストされたループに問題があることに気付きました。

たとえば、次のようなものを考えてください:

`for (it=begin(); it!=end();i++)
{
    for (; it!=end();i++)
    {
    }
}`

ネストされたループが完了すると、イテレータが増加します-そして、親ループはそれを再び増加します! I.e. そのようなことがあれば、「end()+ 1」になります。 その結果、親ループは次のチェックでこのエラーをスローします。

これを回避するために、子ループの後に次の行を挿入しました。

`if (it == vStringList.end()) --it;`

汚れていますが、動作します:D

私はそれが一部に明らかかもしれないことを知っています、しかし私はしばらくの間これの上で私の頭をひっかいてきました、笑


1


削除された要素、またはベクターのeraseメソッドが呼び出されたときに削除された要素の後の要素を指すイテレーターは無効になります。 Eraseメソッドは、ベクター内の次の要素を指す有効なイテレーターを返します。 そのイテレータを使用して、ループを継続し、無効化されたイテレータをインクリメントしないでください。 また、clearメソッドを使用して、ベクター内のすべての要素を削除することもできます。 ただし、要素に割り当てられたメモリを明示的に割り当て解除することを忘れないでください。


1


このコードはベクターのすべてのコンテンツをリークします-ループ内で「delete * deleteIterator」もしなければなりません。 「ベクター」の内容として「ベース」の代わりに「ベース」を使用すると、これらすべてを回避できます。その後、「clear()」がそれらを破棄します。 または、生のポインターが必要な場合は破棄を自動化する「boost

ptr_vector」を使用します。

このような前方反復での `erase()`の呼び出しは、現在の位置より上のすべての要素を下に移動して要素が連続するようにする必要があるため、 `vector`が大きい場合、非常にコストがかかります。 このような理由から、提案するタイプの手動消去は避けてください。


0


ベクトル反復子は増分可能ですが、要素を削除すると、ベクトルの内容が変更されるため、反復子は無効になります。

したがって、オブジェクトを削除する場合は、次の有効な反復子を提供する `erase()`の戻り値を使用する必要があります。