2

これは私の一般的な C++ ゲーム ループです。

std::vector<std::unique_ptr<State>> states;

while(window.isOpen())
{
    //event checking and other stuff

    for(size_t i = 0; i < states.size(); i++)
    {
        states[i]->Update();

        //clear backbuffer
        states[i]->Draw(window);
        //draw backbuffer
    }
}

問題は、リストから状態を削除するたびにstates、プログラムがクラッシュすることです。状態が削除されると、オブジェクトが明らかに存在しなくなったため、オブジェクトを使用できなくなるためだと思います。

statesこれを修正する最善の方法は、ベクター内の状態を新しいものにコピーし、ベクターに必要な変更を加えてstates、ループ中に変更が行われないようにすることだと確信しています。

だからこれは私が思いついたものです:

std::vector<std::unique_ptr<State>> states;
std::vector<State> tempStates;

while(window.isOpen())
{
    //event checking and other stuff

    for(size_t i = 0; i < states.size(); i++)
    {
        tempStates.push_back(*states[i]);
    }

    for(size_t i = 0; i < tempStates.size(); i++)
    {
        tempStates[i].Update();

        //clear backbuffer
        tempStates[i].Draw(window);
        //draw backbuffer
    }

    tempStates.clear();
}

error C2259: 'State' : cannot instantiate abstract classしかし、アプリケーションをビルドすると、 in fileというエラーが表示されますxmemory0。「状態」は、他の状態が継承する抽象基本クラスです。その抽象クラスをインスタンス化していないため、このエラーが発生する理由がわかりません。それを継承するクラスをインスタンス化しています。オブジェクトでstatesいっぱいではありませんそれから継承するオブジェクトでいっぱいです。ある意味でオブジェクトでいっぱいになると思いますが、インスタンス化していません。StateState

では、なぜこのエラーが発生するのですか?どうすれば解決できますか?

ありがとう。

編集

statesこれは基本的に、上記の最初の方法を使用するときに内部の要素が削除される方法です。これは、から継承するクラス内にありStateます。

void Update()
{
    if(/*whatever*/)
    {
        StateManager::RemoveState(std::unique_ptr<State>(this));
        //call stack comes back here but cant because this no longer exists
    }
}

StateManager.cpp

void StateManager::RemoveState(std::unique_ptr<State> state)
{
    states.erase(std::remove(states.begin(), states.end(), state), states.end());
}
4

1 に答える 1

2

おそらく、削除したい要素を転送するのは簡単でしょう:

std::vector<unique_ptr<state>> states;

while ( /* stuff */)
{
    std::vector<unique_ptr<state>> temp;

    for (std::size_t i = 0; i != states.size(); ++i)
    {
        if ( /* move? */)
        {
            temp.push_back(std::move(states[i]));
        }
    }

    for (std::size_t i = 0; i != temp.size(); ++i)
    {
        // process temp[i]
    }
}

削除された要素はstates、各ループ本体の最後でベクター内の null ポインターになるため、それらを削除したい場合があります。

states.erase(std::remove(states.begin(), states.end(), nullptr), states.end());

(現時点ではstd::copy_ifandstd::move_ifアルゴリズムはありませんが、標準ライブラリに追加されると、このコードはずっと短くなります。)

于 2013-01-21T00:47:35.880 に答える