Expression: vector iterators incompatible 错误通常是在使用 C++ 的标准库容器时发生的,特别是 std::vector
,当迭代器失效或者不兼容时。对C++不太熟,记录一个比较有意思的bug。
学弟的一段打怪兽游戏代码
void spawnTreasure() {
float x = static_cast<float>(std::rand() % (window.getSize().x - 20));
float y = static_cast<float>(std::rand() % (window.getSize().y - 20));
treasures.push_back(Treasure(treasureTexture, x, y));
} for (auto it = treasures.begin(); it != treasures.end(); /* 空 */) {
if (dog->getBounds().intersects(it->getBounds())) {
if (soundEnabled) {
dog->bark();
}
score++;
updateScoreText();
it = treasures.erase(it);
spawnTreasure();
}
else {
++it;
}
}
主要的问题出在spawnTreasure
函数调用的位置上。当你在删除一个元素并立即在相同的循环中调用 spawnTreasure
时,可能会导致迭代器失效。因为 spawnTreasure
添加了一个新元素到 treasures
中,这可能会引起容器重新分配内存,从而使得所有现有的迭代器失效。
一种常见的解决方案是将spawnTreasure
的调用推迟到循环外,以避免在迭代器失效的情况下操作容器。使用一个布尔变量来标记是否需要生成新的宝藏,并在循环结束后生成新的宝藏。
void spawnTreasure() {
float x = static_cast<float>(std::rand() % (window.getSize().x - 20));
float y = static_cast<float>(std::rand() % (window.getSize().y - 20));
treasures.push_back(Treasure(treasureTexture, x, y));
}
void checkTreasureCollision() {
bool shouldSpawnTreasure = false;
for (auto it = treasures.begin(); it != treasures.end(); /* 空 */) {
if (dog->getBounds().intersects(it->getBounds())) {
if (soundEnabled) {
dog->bark();
}
score++;
updateScoreText();
it = treasures.erase(it);
shouldSpawnTreasure = true;
} else {
++it;
}
}
if (shouldSpawnTreasure) {
spawnTreasure();
}
}