如何在 for 循环C++中删除向量中的元素

How can I delete an element from my vector while in a for loop C++

本文关键字:删除 向量 元素 C++ for 循环      更新时间:2023-10-16
void foodAgainstCreatures(vector<creature>& displayCreatures, vector<Food>& displayFood)
{
bool hungry = true;
int differenceInX = 0;
int differenceInY = 0;
for (unsigned int j = 0; j < displayCreatures.size(); j++)
{
    hungry = true;
    for (unsigned int i = 0; i < displayFood.size(); i++)
    {
        differenceInX = displayCreatures[j].getXValue() - displayFood[i].getXValue();
        differenceInY = displayCreatures[j].getYValue() - displayFood[i].getYValue();
        if ((differenceInX <= 5 && differenceInX >= -5) && (differenceInY <= 5 && differenceInY >= -5))
        {
            displayCreatures[j].addToEnergy(3);
            displayFood.erase(displayFood.begin() + i);
            hungry = false;
        }
        else
        {
            if (displayCreatures[j].getEnergy() == 0)
            {
                displayCreatures.erase(displayCreatures.begin() + j);
            }
        }
    }
    if (hungry == true)
    {
        displayCreatures[j].addToEnergy(-1);
    }
}
}
一旦"生物"吃"了"食物",

它就会获得"能量",这工作正常,我需要帮助的是将已经"吃掉"的"食物"从载体中删除。 我可以在循环中执行此操作吗?

你有几个选择.
1.以相反的顺序迭代向量,这样删除不会影响您将要访问的元素.
2. 使用更合适的集合,如 list.
3.如果顺序不重要,可以使用"快速删除",只需将当前项目替换为最后一个,减小当前索引和向量大小即可。

是的,您可以在循环中删除项目。由于使用索引来访问项目,因此必须确保索引有效。

std::vector<int> container = {...};
for (std::size_t i = 0; i < container.size(); ++i) {
    if (shouldRemove(container[i]) {
        container.erase(container.begin() + i);
        --i; // We don't want to miss the next item
        continue;
    }
}

但有时您可能希望使用迭代器。当您使用基于范围的 for 循环时,您也在使用迭代器。这样的东西是无效的:

std::vector<mystruct_t> container = {...};
for (mystruct_t &item : container) {
    if (item.please_remove_an_item) {
        container.erase(container.begin() + item.the_item_to_be_removed);
    }
}

使用迭代器时可以执行的操作取决于容器的类型。你可以在这里找到一些关于它的规则。使用 std::vector 时,删除条目后不允许使用迭代器。由于erease将迭代器返回到下一个迭代器,因此可以执行以下操作:

auto it = container.begin();
while (it != container.end()) {
    if (shouldRemove(*it)) {
        it = container.erase(it)
        continue;
    }
    ++it;
}

不应同时按索引迭代和删除。正确的方法是通过迭代器擦除。根据周围的代码,您可以像下面这样发送:

for (auto it = displayCreatures.begin(); it != displayCreatures.end(); ) {
    if (need_to_erase(it)) {
        it = container.erase(it)
        continue;
    }
    ...
    ++it;
}

upd:我编辑了,因为代码中的拼写错误-- .擦除移动迭代器(这就是整个想法),在这种情况下++不需要