C ++如何在迭代时从向量中擦除

时间:2018-08-16 06:05:27

标签: c++

for (int j = 0; j < height + 2; j ++){
    for (int i = 0; i<width+2; i++){
        printw("#");
    }
    printw("\n");
}

当从向量中删除某些内容时,此代码在for循环的开头崩溃。我不懂为什么。如果有帮助,我正在使用Visual Studio 2015

5 个答案:

答案 0 :(得分:11)

erase返回下一个迭代器。

if ((*a) == 2)
{
    delete a;
    it = intList.erase(it);
}

编辑: remove()remove_if()将复制元素(此处为指针),最后将有多个指向同一整数的元素,如果您尝试释放它们,则将剩下悬挂的指针。 / p>

考虑矢量有4个元素,看起来像

0x196c160 0x196bec0 0x196c180 0x196bee0 

可能会想使用erase-remove惯用语

auto temp = remove_if(vec.begin(),vec.end(),[](const auto &i){return *i==2;});

现在看起来像

0x144aec0 0x144b180 0x144b180 0x144aee0

temp将指向3rd元素和一个

for(auto it=temp;it!=vec.end();it++)
    delete *it;

现在第二个元素是一个悬空指针。

编辑2: 如果您在复制元素之前delete,可以解决以上问题。请查看@Dietmar的答案。

答案 1 :(得分:3)

最好使用std::vector<std::unique_ptr<int>>(如果不需要指针,甚至可以使用std::vector<int>)。

然后只使用擦除删除习惯用语:

std::vector<int> intList{3, 2, 1};

intList.erase(std::remove(intList.begin(), intList.end(), 2), intList.end());

std::vector<std::unique_ptr<int>> intList;
intList.puch_back(std::make_unique<int>(3));
intList.puch_back(std::make_unique<int>(2));
intList.puch_back(std::make_unique<int>(1));

intList.erase(std::remove_if(intList.begin(), intList.end(),
                             [](const auto& p){ return *p == 2; }),
              intList.end());

如果您确实需要原始拥有指针,则可以使用partition使用变体:

std::vector<int*> intList{ new int {3}, new int {2}, new int{1} };

auto it = std::partition(intList.begin(), intList.end(),
                         [](const auto& p){ return *p != 2; });

std::foreach (it, intList.end(), [](int* p) { delete p; });
intList.erase(it, intList.end());

最后,如果您确实需要手动执行此操作,则必须将擦除行固定为:

it = intList.erase(it);

拥有:

std::vector<int*> intList{ new int {3}, new int {2}, new int{1} };

for (auto it = intList.begin(); it != intList.end(); /*Empty*/) {
    int *p = *it;

    if (*p == 2) {
        delete p;
        it = intList.erase(it);
    } else {
        ++it;
    }
}

答案 2 :(得分:2)

该代码导致迭代器无效。

您要删除一个,然后希望您的迭代器(只是一个指针)知道发生了什么。

如果您必须遍历整个向量,则考虑保留/丢弃并使用该向量的临时向量。

或者更好,只是使用find http://www.cplusplus.com/reference/algorithm/find/

答案 3 :(得分:2)

如果您查看documentation,擦除功能将返回下一个迭代器。就您而言,使用it = intList.erase(it)是解决方案。在c ++ 11之后,其他容器中的所有擦除功能都遵循相同的想法。

答案 4 :(得分:2)

简单的答案是:您不知道!取而代之的是,您使用两步方法:首先删除元素,然后调整容器的大小。使用原始指针会使事情稍微复杂一些,但仍然可以实现:

auto end = std::remove_if(intList.begin(), intList.end(),
    [](int *ptr){ return *ptr == 2 && (delete ptr, true); });
intList.erase(end, endList.end());

尝试在std::vector上进行迭代时擦除单个元素具有非线性的最坏情况复杂度。