【问题标题】:C++ how can i remove vector of pointers in my gameC ++如何在我的游戏中删除指针向量
【发布时间】:2015-02-04 16:28:23
【问题描述】:

我试图让第一款游戏类似于坦克。但是当我尝试删除敌方坦克时我的游戏崩溃了(有时有效,有时无效),我不知道我的代码有什么问题。你会帮我吗?

void Game::update(sf::Time elapsedTime){

if (enemies.size() < 6){

    eTank1 = new EnemyTank(150, 130);
    enemies.push_back(eTank1);
    }

    tank->move(elapsedTime);

for (vector<EnemyTank*>::const_iterator it = enemies.begin(); it != enemies.end();)
{

    if (collision->checkCollisionWithEnemyTankAndTank(tank, *it)){
        (*it)->move(elapsedTime);
    }


    collision->checkShoot(tank->getBulletsVector(), tank, *it); 

    //probably there is a problem
    if ((*it)->getlife() <= 0){

        delete  *it;            
        enemies.erase(it);
        cout << "TANGO DOWN" << endl;
    }
     ++it;
}

checkShoot 看起来像这样:

void Collision::checkShoot(vector <Bullet*> &bullet, Tank *tank, EnemyTank* enemyTank){

distance = 0;

for (int i = 0; i < bullet.size(); i++){


    distance = abs(bullet[i]->getPosition().x - enemyTank->getPosition().x) + abs(bullet[i]->getPosition().y - enemyTank->getPosition().y);

    if (distance < 45){
        cout << "act life: " << enemyTank->getlife() << endl;
        enemyTank->setLife();       // -0.5 from actual life        
        tank->setVector(i);         // delete bullet from vector        

    }

}

}

以及析构函数的代码

cout << "DESTRU";
delete tank_bullet;

for (auto &it : bullets){ delete it; } bullets.clear();


cout << "DESTRU T - END\n";

最后是 setVector(i);

void setVector(int index){
     if (!bullets.empty()){
        delete (bullets.at(index));
        bullets.erase(bullets.begin() + index);
    }

}

【问题讨论】:

  • 你不能盲目地 erase 来自你正在迭代的向量,因为 erase 将使迭代器无效。但是,您可能对 erase 函数返回的内容感兴趣。
  • 谷歌“擦除删除成语”。
  • 你能给我更多关于我的问题解决方案的信息吗?我不完全知道如何解决这个崩溃。谢谢。
  • @user3419495 正如 Joachim 指出的那样,您应该将擦除的返回值分配给迭代器 it = enemies.erase(it); 而不是 ++it
  • 您有可能错过了@alarge 在他的回答中指出的将++it 放入else 分支的微小信息:)。您还应该考虑您的容器,因为如果元素不在向量本身的末尾,则从向量中删除是一项特别复杂的操作。但是,如果您不经常删除它可能仍然是一个不错的选择。您也可以将要删除的元素与向量的背面交换,如果元素的顺序无关紧要,只需调用 pop_back() 函数。

标签: c++ pointers memory-leaks sfml


【解决方案1】:

答案确实在 cmets 中,但如果他们觉得太简洁,我会写一个稍微长一点的解释。

这是一个与您的代码风格相似的最小示例:

int main() {
  auto v = std::vector<int> {1, 2, 3, 4, 5};
  for(auto it = v.cbegin(); it != v.cend(); ) {
    if(*it == 5)
      v.erase(it);
    ++it;
  }
}

此段错误(如果您与不是vector 的最后一个元素的东西进行比较,例如*it == 3,则不会,但此行为可能与编译器有关)。为什么? v.erase(it) 使迭代器 it 无效,因此您不能在该行之后使用 it。相反,您应该使用erase 返回的it = v.erase(it),它是被删除的迭代器之后的迭代器。现在,如果它恰好是 v.cend() 并且在下一行你增加它,++it,那么你就出界了,运气不好。

我不鼓励您使用以下内容,但是如果您想保持代码的风格,那么应该是

if(*it == 5)
  it = v.erase(it);
else
  ++it;

else 的作用是避免erase 的双重递增。

【讨论】:

    猜你喜欢
    • 2020-06-24
    • 1970-01-01
    • 1970-01-01
    • 2013-07-02
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 2010-09-08
    • 2021-06-14
    相关资源
    最近更新 更多