C++通过改变vector.size()进行迭代

C++ iterating with changing vector.size()

本文关键字:迭代 size 改变 vector C++      更新时间:2023-10-16

我写了一些可能很幼稚的代码,旨在从向量中删除过于相似的元素。功能很好,但我认为由于向量的动态调整,我有时可能会得到意想不到的结果。

for (size_t i = 0 ; i < vec.size(); i++) {
    for(size_t j = i+1; j < vec.size(); j++) {
        if(norm(vec[i]-vec[j]) <= 20 ) {
            vec.erase(vec.begin()+j);
        }
    }
}

这样做安全吗?当我擦除元素时,我担心I和j是否正确地适应。

您需要更加注意元素的位置。直接用迭代器表达这一点可能比通过索引计算迭代器更容易,比如:

for (auto it = vec.begin(); it != vec.end(); ++it)
{
    for (auto jt = std::next(it); jt !=; vec.end(); )
    {
        if (/* condition */)
        {
            jt = vec.erase(jt);
        }
        else
        {
            ++jt;
        }
    }
}
是的,你在这里很安全。由于您使用的是索引,而不是迭代器,因此除了大小之外,没有什么可以通过擦除容器中的项来使其无效,并且大小将自动更新,因此我们在这里做得很好。

还要考虑的一件事是,擦除内循环内的元素对外循环的停止条件有什么影响。这也没有问题,因为j被保证严格大于i,所以内循环的j < vec.size()条件将在外循环的i < vec.size()条件之前被满足,这意味着不存在具有无效索引i的不安全的vec[i]访问。

当然,您应该在擦除元素后增加j,以避免出现经典错误。一个更好的方法是从后面开始遍历向量,但您需要在两个循环中都这样做,以确保i(一个有效元素)永远不会从i的外部索引下面擦除。