C++ 向量擦除迭代器

C++ 向量擦除迭代器,c++,vector,iterator,C++,Vector,Iterator,我有以下代码: int main() { vector<int> res; res.push_back(1); vector<int>::iterator it = res.begin(); for( ; it != res.end(); it++) { it = res.erase(it); //if(it == res.end()) // return 0; } } i

我有以下代码:

int main()
{
    vector<int> res;
    res.push_back(1);
    vector<int>::iterator it = res.begin();
    for( ; it != res.end(); it++)
    {
        it = res.erase(it);
        //if(it == res.end())
        //  return 0;
    }
}
intmain()
{
向量res;
res.push_back(1);
向量::迭代器it=res.begin();
for(;it!=res.end();it++)
{
它=清除(它);
//if(it==res.end())
//返回0;
}
}
一个随机访问迭代器,指向函数调用删除的最后一个元素后面的元素的新位置,如果操作删除了序列中的最后一个元素,则该位置为向量结束

这段代码崩溃了,但是如果我使用
if(it==res.end())
部分,然后返回,它就会工作。怎么会?for循环是否缓存
res.end()
以使不相等运算符失败?

res.erase(it)
始终返回下一个有效迭代器,如果删除最后一个元素,它将指向
.end()

在循环结束时,
++it
始终被调用,因此您可以递增
.end()
,这是不允许的

不过,简单地检查
.end()
仍然会留下一个错误,因为每次迭代都会跳过一个元素(
it
通过
.erase()
的返回“递增”,然后通过循环再次递增)

您可能需要以下内容:

 while (it != res.end()) {
        it = res.erase(it);    
 }
删除每个元素

(为了完整性:我假设这是一个简化的示例,如果您只想让每个元素都消失,而不必对其执行操作(例如删除),则只需调用
res.clear()

当您仅有条件地擦除元素时,您可能需要以下内容

for ( ; it != res.end(); ) {
  if (condition) {
    it = res.erase(it);
  } else {
    ++it;
  }
}

不要擦除然后递增迭代器。无需增加,如果向量的元素数为奇数(或偶数,我不知道),您将错过向量的末尾。

it++指令在块的末尾完成。因此,如果您正在擦除最后一个元素,那么您将尝试递增指向空集合的迭代器。

您递增
超过for循环的循环表达式中(空)容器的末尾

for( ; it != res.end();)
{
    it = res.erase(it);
}
或者更一般地说:

for( ; it != res.end();)
{
    if (smth)
        it = res.erase(it);
    else
        ++it;
}

以下几点似乎也起作用:

for (vector<int>::iterator it = res.begin(); it != res.end(); it++)
{
  res.erase(it--);
}
for(vector::iterator it=res.begin();it!=res.end();it++)
{
清除(它--);
}
不确定这是否有任何缺陷?

if(allPlayers.empty()==false){
if(allPlayers.empty() == false) {
    for(int i = allPlayers.size() - 1; i >= 0; i--)
    {
        if(allPlayers.at(i).getpMoney() <= 0) 
            allPlayers.erase(allPlayers.at(i));
    }
}
对于(int i=allPlayers.size()-1;i>=0;i--) {
if(allPlayers.at(i).getpMoney()作为对crazylammer答案的修改,我经常使用:

your_vector_type::iterator it;
for( it = res.start(); it != res.end();)
{
    your_vector_type::iterator curr = it++;
    if (something)
        res.erase(curr);
}

这样做的好处是,您不必担心忘记递增迭代器,这样当您有复杂的逻辑时,迭代器就不那么容易出现错误,它将位于下一个元素,无论您是否从向量中删除它。

因为方法erase in vector返回传递的迭代器的下一个迭代器

我将给出如何在迭代时删除向量中的元素的示例

void test_del_vector(){
    std::vector<int> vecInt{0, 1, 2, 3, 4, 5};

    //method 1
    for(auto it = vecInt.begin();it != vecInt.end();){
        if(*it % 2){// remove all the odds
            it = vecInt.erase(it); // note it will = next(it) after erase
        } else{
            ++it;
        }
    }

    // output all the remaining elements
    for(auto const& it:vecInt)std::cout<<it;
    std::cout<<std::endl;

    // recreate vecInt, and use method 2
    vecInt = {0, 1, 2, 3, 4, 5};
    //method 2
    for(auto it=std::begin(vecInt);it!=std::end(vecInt);){
        if (*it % 2){
            it = vecInt.erase(it);
        }else{
            ++it;
        }
    }

    // output all the remaining elements
    for(auto const& it:vecInt)std::cout<<it;
    std::cout<<std::endl;

    // recreate vecInt, and use method 3
    vecInt = {0, 1, 2, 3, 4, 5};
    //method 3
    vecInt.erase(std::remove_if(vecInt.begin(), vecInt.end(),
                 [](const int a){return a % 2;}),
                 vecInt.end());

    // output all the remaining elements
    for(auto const& it:vecInt)std::cout<<it;
    std::cout<<std::endl;

}
一种更有效的生成方法:

template<class Container, class F>
void erase_where(Container& c, F&& f)
{
    c.erase(std::remove_if(c.begin(), c.end(),std::forward<F>(f)),
            c.end());
}

void test_del_vector(){
    std::vector<int> vecInt{0, 1, 2, 3, 4, 5};
    //method 4
    auto is_odd = [](int x){return x % 2;};
    erase_where(vecInt, is_odd);

    // output all the remaining elements
    for(auto const& it:vecInt)std::cout<<it;
    std::cout<<std::endl;    
}
模板
无效删除位置(容器和c、F和F)
{
c、 擦除(std::remove_if(c.begin()、c.end()、std::forward(f)),
c、 end());
}
无效测试_del_vector(){
向量向量{0,1,2,3,4,5};
//方法4
自动为奇数=[](int x){返回x%2;};
擦除其中的(向量,是奇数);
//输出所有剩余的元素

对于(Autoconst & I:VECTEN)STD::CUT

你可以用现代C++做的事情是使用“STD::ReaveVIIF”和lambda表达式; 此代码将删除向量的“3”

vector<int> vec {1,2,3,4,5,6};

vec.erase(std::remove_if(begin(vec),end(vec),[](int elem){return (elem == 3);}), end(vec));
向量向量{1,2,3,4,5,6};
向量擦除(std::remove_if(begin(vec),end(vec),[](int-elem){return(elem==3);},end(vec));

类似的问题:因为这只是对代码的简化,所以我并没有试图删除实际代码中的所有元素OK,所以它首先递增,递增后比较No,hidayat;您的代码试图逐个删除向量中的所有元素。为此,您应该从
res.begin()开始
,然后永远不要推进迭代器,而是在删除元素时检索返回的迭代器(所有STL容器也是如此)。增量本身就是错误的部分。在真正的代码中,我并没有试图删除所有元素,但谢谢,我现在明白我做错了什么。嗨,我也这么做了,但我仍然得到了“超出范围”的错误。你能告诉我为什么吗?@DukeLover当它等于
.end()时,你必须执行
迭代器+
在某个地方,没有看到任何我能猜到的代码。如果你想不出来,可能会提出一个问题?为什么不使用
while
?@chamini2 a
while
循环在这种情况下是等效的。虽然这段代码可以回答问题,但最好解释它的功能并添加一些引用。我不确定c上面的ode。我看到了3个主要问题。首先,在删除后,您不会将res.erase(it)重新签回
it
。在删除内容时,您不能让it++在迭代器语句中,因此您应该有一个条件检查来删除它。如果条件失败,那么您应该迭代到下一个(
it++
)。虽然我想知道你为什么有
它--
?对不起,你为什么还要减少迭代器?如果是这样的话,也许我会绊倒,我道歉。@VG谢谢,我想你的评论解决了答案中的问题,因此很有教育意义,也许值得一提。恐怕我不理解
它--
不管怎样,从那以后,桥下流了太多的水…@SkippyleGrandGourou感谢你的回复,我还没有找到与上述递减状态相匹配的东西。这可能是移除后重复一步的情况吗?可能与
it=res.erase(it)相同
?尽管我真的很怀疑。Hmmmm@VG:根据Pieter的回答,“
res.erase(it)
总是返回下一个有效的迭代器”。我猜
it--
it++
取消,所以据我所知,这段代码一直在擦除
vector<int> vec {1,2,3,4,5,6};

vec.erase(std::remove_if(begin(vec),end(vec),[](int elem){return (elem == 3);}), end(vec));