2

共有ポインターのベクトルを使用して、customer と呼ばれるゲーム キャラクターを含めます。

typedef std::shared_ptr<Customer> customer;
std::vector<customer> customers;

customers.push_back(customer(new Customer()));

for(int i = 0; i < customers.size(); i++)
{
    if(customers[i]->hasLeftScreen())
    {
        if(!customers[i]->itemRecieved())
            outOfStocks++;
        // Kill Character Here
    }       
}

以前はベクトルを使用してオブジェクトを保持していたので、ベクトルで消去を呼び出してイテレータを渡すことに慣れています。私の質問は、上記のコード スニペットのベクトルからポインターを削除する方法はありますか? ここでは、コードを単純化するためにイテレータを使用しないことを望んでいました。また、ポインターが画面から消えると、私はゲームから削除される顧客だったので、ポインターを削除する必要があります。

どうもありがとう

4

3 に答える 3

3

率直に言って、はるかに扱いやすいイテレータの使用を検討してください。それらに対するあなたの嫌悪感はわかりませんが、以下を参照してください。

std::vector<customer>::iterator it = customers.begin();
while (it != customers.end())
{
    if(it->hasLeftScreen())
    {
        if(!it->itemRecieved())
            outOfStocks++;
        it = customers.erase(it);
        continue;
    }
    ++it;
}

これにより、ベクターから共有ポインター インスタンスが削除されます。インスタンスが共有ポインターへの最後の参照である場合、その顧客の関連メモリも解放し、そのデストラクタを起動するなど... (最初にスマート共有ポインターを使用するポイントと、スマートポインターを使用するための小道具、 ところで)。

于 2013-03-11T16:56:00.853 に答える
2

常に反復子を使用する必要があります。これは C++ のイディオムです。これにより、コードが次のように変更されます...

for(auto i = customers.begin(); i != customers.end(); ++i)
{
    if((*i)->hasLeftScreen())
    {
        if(!(*i)->itemRecieved())
            outOfStocks++;
        // Kill Character Here
    }       
}

さて、明らかです。代わりに、erase-remove イディオムを使用します。

int outOfStocks = 0;
auto it = std::remove_if(customer.begin(), customers.end(), [&](Customer const& i) {
    if(i->hasLeftScreen()) {
        if(!i->itemRecieved()) {
            outOfStocks++;
        }
        return true;
    }
    return false;
}
std::erase(it, customers.end());
于 2013-03-11T16:57:41.517 に答える
0

「イテレータ演算」を利用することもできます:

        // Kill Character Here
        customers.erase(customers.begin() + i);

...しかしcustomers.size()、コンテナが縮小するにつれて現在のインデックスが無効になるという問題があります。

また、削除する顧客を明示的に指定する必要はありませんdelete。これは、スマート ポインターが処理するためです。

于 2013-03-11T17:00:21.953 に答える