使用擦除方法

时间:2016-02-03 19:17:48

标签: c++ c++11

这里有一小段代码,这让我们有点生气......

for (vector<QSharedPointer<Mine>>::iterator itMine = _mines.begin(); 
       itMine != _mines.end();) {
    auto point2 = shipFire[l].getBulletLine().p2();
    if (_mines[pos]->checkCollision(point2)) { // _mines is a Vector<QSharedPointer<Mine>>
        Explosion explosionMine(_mines[pos]->point());
        _explosions.push_back(explosionMine);
        itMine = _mines.erase(itMine);
        bulletErased = true;
        scoreFrame += 100;
    }
    else {
        ++itMine;
        pos++;
    }
}

问题是,itMine正在删除我们vector<..<Mine>>中的两个,并且正在使程序意外关闭

我们考虑过这个问题,想出了这个:我的所有迭代器在删除了我的一个之后都失效了,对吗?

但我们对如何更改我们的实际代码以适应新代码感到有些困惑?

主要问题是:我们如何重置这个呢?

ps:如果您有任何疑问,或者您需要更多代码来理解背后的逻辑,请随时提出更多问题!

最诚挚的问候,并提前感谢你。

2 个答案:

答案 0 :(得分:0)

这个问题的一个非常罕见的解决方案是将当前位置与后退位置交换。然后可以删除最后一项而不会使任何迭代器失效。请参阅live example

#include <iostream>
#include <vector>
#include <memory>

int main()
{
    struct Mine
    {
        Mine( int id = 0 ): id( id ) { }
        bool check_collision_point( int point ) const { return id % point == 0; }
        int id; 
    };

    auto mines = std::vector<std::shared_ptr<Mine>>{ 7 };

    for( auto i = 0u; i < mines.size(); ++i )
    {
        mines[i] = std::make_shared<Mine>( i );
    }

    // save point outside loop
    auto point = 2;

    for( auto it = mines.begin(); it != mines.end(); )
    {
        // don't use mines[pos] in loop
        if( (*it)->check_collision_point( point ) ){
            std::iter_swap(it, mines.rbegin() );
            mines.resize( mines.size() -1 );
        }
        else
            ++it;
    }

    for( auto it = mines.begin(); it != mines.end(); ++it)
        std::cout << (*it)->id << " "; 
}

答案 1 :(得分:0)

更新

   for (auto itMine = _mines.begin(); itMine != _mines.end();){
            auto point2 = shipFire[l].getBulletLine().p2(); // thomas : -> here we need to do it in the loop, to get every bullet position while looping.

            if (_mines[pos]->checkCollision(point2)){
                Explosion explosionMine(_mines[pos]->point());
                _explosions.push_back(explosionMine);
                if (_mines[pos]->checkCollision(point2)){
                    mines_to_be_deleted.push_back(*itMine);
                    shipFire.erase(it);
                    bulletErased = true;
                    scoreFrame += 100;
                    qDebug() << "Collision bullet mine";

                }
            }
            //else
            ++itMine;
            pos++;
        }


        for (auto itrDelete = mines_to_be_deleted.begin(); itrDelete != mines_to_be_deleted.end();)
        {
                _mines.pop_back(); // Here instead of that, we need to erase the current itr (here is our mistake) 
                //mines_to_be_deleted.erase(itrDelete);
                //_mines.resize(_mines.size());
                qDebug() << "mine deleted";
                ++itrDelete;
        }
        mines_to_be_deleted.clear();

此时我们想出了这个。 我们尝试了你告诉我们的所有内容,但没有一个有效,我们考虑将当前的itr交换到向量的末尾。谢谢你的帮助。

目前,该计划运行得非常好,但是当我们用一颗子弹击中一枚地雷时,一只手枪就会消失。

对于那些想要了解的人,我们找到了解决方案。

while(!mines_to_be_deleted.empty()) { // _mine_to_be_deleted is a QList<Sharedpointer<Mine>>
        std::remove(begin(_mines),end(_mines),mines_to_be_deleted.front());
        _mines.pop_back();
        mines_to_be_deleted.pop_front();
    }

使用std :: remove允许我们擦除Mine而不创建malloc()