4

さまざまな子クラスをそこに格納できるようにするために、仮想基本クラスへのポインターのベクトルを保持するマネージャー クラスがあります。このマネージャ クラスのデストラクタで、保持しているすべてのポインタを循環して削除したいと考えています。ただし、遭遇した多くの方法を試しましたが、実行中にプログラムがクラッシュし続けます。

私が持っている現在のコードを以下に示します:-

for (std::vector<GameState*>::iterator it = gamestates_.begin(); it != gamestates_.end(); ++it){
    delete *it;
    it = gamestates_.erase(it);
}

私がまだ試していないことの 1 つは、unique_ptr を使用することですが、これを使用しなくても処理できるはずです。私が間違っている場合は、私を修正してください。

編集: ループの後にベクトルをクリアする必要があることは承知していますが、これは、ポインターを削除する通常の方法をすべて試した結果です。削除コマンドが気に入らないようです。

4

6 に答える 6

6

ベクターから要素を消去すると、反復子が無効になるため、後で反復を続けることはできません。この場合、ループ内の要素を消去しません。その後、ベクトルをクリアします。

for (auto it = gamestates_.begin(); it != gamestates_.end(); ++it){
    delete *it;
}
gamestates_.clear();

ただし、これがデストラクタにあり、ベクトルが破棄されようとしている場合は、それをクリアしても意味がありません。

ループ内で消去する必要がある場合 (おそらく一部の要素のみを消去したいため)、反復子を有効に保つためにもう少し注意が必要です。

for (auto it = gamestates_.begin(); it != gamestates_.end();){ // No ++ here
    if (should_erase(it)) {
        it = gamestates_.erase(it);
    } else {
        ++it;
    }
}

まだ試していないことの 1 つは使用unique_ptrですが、これを使用しなくても処理できるはずです。私が間違っている場合は、私を修正してください。

これにより動的オブジェクトをストリームで管理したい場合は、必ず3 つのルールに従ってください。「浅い」コピーを防ぐために、コピー コンストラクターとコピー代入演算子を実装 (または削除) する必要があります。同じオブジェクトを削除しようとする 2 つのベクトル。また、オブジェクトを削除または置換する他の場所にあるオブジェクトを削除するように注意する必要があります。スマート ポインター (またはポリモーフィズムにポインターが必要ない場合はオブジェクト自体) を格納すると、これらすべての処理が行われるので、常にそれをお勧めします。

ループの後にベクトルをクリアする必要があることは承知していますが、これは、ポインターを削除する通常の方法をすべて試した結果です。削除コマンドが気に入らないようです。

最も可能性の高い原因は、3 つのルールに従っておらず、ベクトルをコピーした後に誤って同じオブジェクトを 2 回削除しようとしたことです。GameStateが基底クラスであり、それに仮想デストラクタを与えるのを忘れていたり、ポインタが他のコードによって破損している可能性もあります。

于 2013-09-02T13:49:58.847 に答える
2

イテレータは各ループで 2 回更新されます。

it = gamestates_.erase(it);

it++

最初のものだけが必要です - それはすでにコンテナ内の「次のオブジェクト」を指しています。

于 2013-09-02T13:50:19.547 に答える
0

ループヘッダーの を取り除き++itます。for

eraseすでにあなたのために進んでいます。

または、反復、削除、反復後.clear()

于 2013-09-02T13:51:17.833 に答える
0

ベクターから要素を消去すると、反復子が無効になります。要素によってオブジェクト ポインターを削除し、次にclear()ベクターのコンテンツを削除します。

于 2013-09-02T13:49:42.653 に答える