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

Luc*_*cas 52 c++ iterator stl

我有一个向量,包含活动或非活动的项目.我希望此向量的大小对于性能问题保持较小,因此我希望从向量中删除已标记为非活动的项目.我在迭代时尝试这样做,但我收到错误"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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Moo*_*ice 65

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

(对于非的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());
Run Code Online (Sandbox Code Playgroud)

  • "这甚至不能用于动态尺寸矢量." 为什么不? (8认同)

Vas*_*lis 48

我同意wilx的回答.这是一个实现:

// curFiles is: vector < string > curFiles;

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

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

    if(aConditionIsMet) {

        it = curFiles.erase(it);
    }
    else ++it;
}
Run Code Online (Sandbox Code Playgroud)


wil*_*ilx 15

你可以这样做,但while()我认为你必须重新调整一下.该erase()函数在删除之后将元素返回到元素:iterator erase(iterator position);.引自23.1.1/7的标准:

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

虽然也许你应该使用Erase-remove习语代替.


Pie*_*rre 7

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

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


Oli*_*rth 0

从向量中间删除项目将使该向量的所有迭代器无效,因此您不能执行此操作(更新:不诉诸 Wilx 的建议)。

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

  • 我知道有点晚了,但你可能想读一下这篇文章。它与大多数人的预期相反,但它来自 C++ 的创建者 http://bulldozer00.com/2012/02/09/vectors-and-lists/ (4认同)