C++ 迭代时从向量中删除项目?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4713131/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:15:31  来源:igfitidea点击:

Removing item from vector while iterating?

c++stliterator

提问by Lucas

I have a vector that holds items that are either active or inactive. I want the size of this vector to stay small for performance issues, so I want items that have been marked inactive to be erased from the vector. I tried doing this while iterating but I am getting the error "vector iterators incompatible".

我有一个包含活动或非活动项目的向量。我希望此向量的大小保持较小以解决性能问题,因此我希望从向量中删除已标记为非活动的项目。我在迭代时尝试这样做,但我收到错误“向量迭代器不兼容”。

vector<Orb>::iterator i = orbsList.begin();

    while(i != orbsList.end()) {
        bool isActive = (*i).active;

        if(!isActive) {
            orbsList.erase(i++);
        }
        else {
            // do something with *i
            ++i;
        }
    }

回答by Moo-Juice

The most readable way I've done this in the past is to use std::vector::erasecombined with std::remove_if. In the example below, I use this combination to remove any number less than 10 from a vector.

我过去做过的最易读的方法是std::vector::erase结合使用std::remove_if. 在下面的示例中,我使用此组合从向量中删除任何小于 10 的数字。

(For non-c++0x, you can just replace the lambda below with your own predicate:)

对于非的C ++ 0x,只需更换下面与您自己的谓词拉姆达:

// a list of ints
int myInts[] = {1, 7, 8, 4, 5, 10, 15, 22, 50. 29};
std::vector v(myInts, myInts + sizeof(myInts) / sizeof(int));

// get rid of anything < 10
v.erase(std::remove_if(v.begin(), v.end(), 
                       [](int i) { return i < 10; }), v.end());

回答by Vassilis

I agree with wilx's answer. Here is an implementation:

我同意威尔克斯的回答。这是一个实现:

// curFiles is: vector < string > curFiles;

vector< string >::iterator it = curFiles.begin();

while(it != curFiles.end()) {

    if(aConditionIsMet) {

        it = curFiles.erase(it);
    }
    else ++it;
}

回答by wilx

You can do that but you will have to reshuffle your while()a bit, I think. The erase()function returns an iterator to the element next after the erased one: iterator erase(iterator position);. Quoting from the standard from 23.1.1/7:

你可以这样做,但while()我认为你必须重新洗牌。该erase()函数返回一个迭代器到被擦除元素之后的下一个元素:iterator erase(iterator position);。引用自 23.1.1/7 的标准:

The iterator returned from a.erase(q) points to the element immediately following q prior to the element being erased. If no such element exists, a.end() is returned.

从 a.erase(q) 返回的迭代器指向在元素被擦除之前紧跟在 q 之后的元素。如果不存在这样的元素,则返回 a.end()。

Though maybe you should be using the Erase-remove idiominstead.

虽然也许您应该改用Erase-remove 成语

回答by Pierre

erasereturns a pointer to the next iterator value (same as Vassilis):

erase返回指向下一个迭代器值的指针(与 Vassilis 相同):

vector <cMyClass>::iterator mit
for(mit = myVec.begin(); mit != myVec.end(); )
{   if(condition)
        mit = myVec.erase(mit);
    else
        mit++;
}

回答by Dawid Drozd

If someone need working on indexes

如果有人需要处理索引

vector<int> vector;
for(int i=0;i<10;++i)vector.push_back(i);

int size = vector.size();
for (int i = 0; i < size; ++i)
{
    assert(i > -1 && i < (int)vector.size());
    if(vector[i] % 3 == 0)
    {
        printf("Removing %d, %d\n",vector[i],i);
        vector.erase(vector.begin() + i);
    }

    if (size != (int)vector.size())
    {
        --i;
        size = vector.size();
        printf("Go back %d\n",size);
    }
}

回答by Raedwald

You might want to consider using a std::listinstead of a std::vectorfor your data structure. It is safer (less bug prone) to use when combining erasure with iteration.

您可能要考虑对数据结构使用 astd::list而不是 a std::vector。将擦除与迭代结合使用时,使用起来更安全(不易出错)。

回答by Maxim Egorushkin

As they said, vector's iterators get invalidated on vector::erase()no matter which form of iterator increment you use. Use an integer index instead.

正如他们所说,vector::erase()无论您使用哪种形式的迭代器增量,vector 的迭代器都会失效。改用整数索引。

回答by Oliver Charlesworth

Removing items from the middle of a vector will invalidate all iterators to that vector, so you cannot do this (update: without resorting to Wilx's suggestion).

从向量中间删除项目将使该向量的所有迭代器无效,因此您不能这样做(更新:不求助于威尔克斯的建议)。

Also, if you're worried about performance, erasing items from the middle of a vector is a bad idea anyway. Perhaps you want to use an std::list?

此外,如果您担心性能,从向量中间擦除项目无论如何都是个坏主意。也许您想使用std::list?