自动迭代迭代通过向量结束(我认为)

  • 本文关键字:迭代 向量 结束 c++
  • 更新时间 :
  • 英文 :


我目前正在尝试用c++和OpenGL编写一款吃豆人游戏。目前,当我试图从"GameObject"指针的向量中删除"Coin"指针时,我遇到了一些麻烦:

bool MovableObject::collisionHandling(std::vector<GameObject*>& v) {
bool deleteCoin = false;
int vectorIt;
for (auto it = begin(v); it != end(v); ++it) {
if (*it != this) {
// If there is a collision imminent:
if (collisionInt(this, *it)) {
// For PacMan:
if (this->classType == "PacMan") {
// Collision with coin:
if ((*it)->classType == "Coin") {
PacMan* ptr = static_cast<PacMan*>(this);
ptr->score += 10;
vectorIt = it - v.begin();
deleteCoin = true;
}
}
}
}
}
if (deleteCoin) {
Coin* ptr = static_cast<Coin*>(v[vectorIt]);
v.erase(v.begin() + vectorIt);
delete ptr;
}
return false;
}

这会在矢量文件中引发一个异常,该异常的内容如下:引发异常:读取访问冲突。_麦康特是nullptr。异常发生在第72行,代码如下:

_STL_VERIFY(_Ptr < _Mycont->_Mylast, "can't increment vector iterator past end")

异常似乎是在另一个for循环之间抛出的,其中collisionHandling函数是从以下位置调用的:

void GameLevel::update(GLFWwindow *window) {
std::string classType;
// Delta time:
float timeSinceStart = float(glfwGetTime());
deltaTime = timeSinceStart - oldTimeSinceStart;
oldTimeSinceStart = timeSinceStart;
if (!paused) {
std::cout << "Testing...";
// We don't need to update walls:
for (auto it = begin(objectsPtr); it != end(objectsPtr); ++it) {
classType = (*it)->classType;
if (classType == "Ghost") {
Ghost* ptr = static_cast<Ghost*>(*it);
ptr->deltaTime = deltaTime;
ptr->pickRandomOffDirection();
ptr->updateSpeed();
ptr->collisionHandling(objectsPtr);
ptr->move();
ptr->animate();
}
else if (classType == "PacMan") {
PacMan* ptr = static_cast<PacMan*>(*it);
ptr->deltaTime = deltaTime;
ptr->input(window);
ptr->updateSpeed();
paused = ptr->collisionHandling(objectsPtr);
ptr->move();
ptr->animate();
}
}
std::cout << "completen";
}

据我所知,这不应该是一个例外。(用int向量测试类似的代码,其中最后一个元素在循环中被擦除,但没有失败。(在我添加了与coin部分的冲突之前,这段代码也能正常工作,所以我知道这与向量循环有关。此外,只有当某些特定的硬币应该被删除时,这才会失败。它们中的大多数都被删除了,没有任何问题。

我感谢任何反馈或尝试帮助我。

为了以防万一您需要更多信息,collisionHandling函数包含了更多的代码,但我认为它与错误无关。这是完整的代码:

bool MovableObject::collisionHandling(std::vector<GameObject*>& v) {
bool deleteCoin = false;
int vectorIt;
for (auto it = begin(v); it != end(v); ++it) {
if (*it != this) {
// If there is a collision imminent:
if (collisionInt(this, *it)) {
// For PacMan:
if (this->classType == "PacMan") {
// Collision with wall:
if ((*it)->classType == "GameObject") {
bool xCollision = false, yCollision = false;
glm::vec2 oldSpeed = speed;
// Check x-axis:
speed.y = 0.f;
xCollision = collisionInt(this, *it);
// Check y-axis:
speed.y = oldSpeed.y;
speed.x = 0.f;
yCollision = collisionInt(this, *it);
speed = glm::vec2(!xCollision * oldSpeed.x, !yCollision * oldSpeed.y);
}
// Collision with ghost
if ((*it)->classType == "Ghost") {
std::cout << "GAME OVERn";
return true;
}
// Collision with coin:
if ((*it)->classType == "Coin") {
PacMan* ptr = static_cast<PacMan*>(this);
ptr->score += 10;
vectorIt = it - v.begin();
deleteCoin = true;
}
}
// For Ghost:
else if (this->classType == "Ghost") {
// Collision with wall:
if ((*it)->classType == "GameObject") {
// Same as with PacMan:
bool xCollision = false, yCollision = false;
glm::vec2 oldSpeed = speed;
// Check x-axis:
speed.y = 0.f;
xCollision = collisionInt(this, *it);
// Check y-axis:
speed.y = oldSpeed.y;
speed.x = 0.f;
yCollision = collisionInt(this, *it);
speed = glm::vec2(!xCollision * oldSpeed.x, !yCollision * oldSpeed.y);
}
}
}
}
}
if (deleteCoin) {
Coin* ptr = static_cast<Coin*>(v[vectorIt]);
v.erase(v.begin() + vectorIt);
delete ptr;
}
return false;
}

感谢rafix07在评论中指出我的错误:

未定义的行为,它在collisionHandling的循环内部更新中无效。collisionHandling在同一个容器上迭代,调用erase

我通过在update方法中的for循环后删除所需对象而不是在collisionHandling方法中删除所需的对象来修复此问题。

最新更新