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

C++ 迭代时从向量中删除项?,c++,stl,iterator,C++,Stl,Iterator,我有一个向量,它包含活动或非活动的项。我希望此向量的大小保持较小,以解决性能问题,因此我希望从向量中删除已标记为非活动的项。我在迭代时尝试过这样做,但得到的错误是“向量迭代器不兼容” vector::迭代器i=orbsList.begin(); 而(i!=orbsList.end()){ bool isActive=(*i).active; 如果(!isActive){ orbsList.erase(i++); } 否则{ //和我一起做点什么 ++一,; } } 从向量中间删除项将使该向量的所

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

vector::迭代器i=orbsList.begin();
而(i!=orbsList.end()){
bool isActive=(*i).active;
如果(!isActive){
orbsList.erase(i++);
}
否则{
//和我一起做点什么
++一,;
}
}

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


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

你可以这样做,但我想你必须稍微重新调整一下
while()
erase()
函数将迭代器返回到被删除元素后的下一个元素:
迭代器擦除(迭代器位置)。引用23.1.1/7中的标准:

从a.erase(q)返回的迭代器 立即指向元素 在元素之前的q之后 删除。如果不存在这样的元素, a、 返回end()


尽管您可能应该改用。

正如他们所说,无论您使用哪种形式的迭代器增量,vector的迭代器在
vector::erase()上都会失效。使用整数索引代替.< /p> ,您可能需要考虑使用<代码> STD::List< <代码>,而不是使用<代码> STD::vector < /代码>用于您的数据结构。在将擦除与迭代结合使用时,使用它更安全(更不容易出现错误)。

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

对于非c++0x,您可以用自己的谓词替换下面的lambda:

//整数列表
int myInts[]={1,7,8,4,5,10,15,22,50.29};
向量v(myInts,myInts+sizeof(myInts)/sizeof(int));
//把<10的东西扔掉
v、 擦除(标准::如果(v.begin(),v.end(),则删除),
[](int i){return i<10;}),v.end();

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

// curFiles is: vector < string > curFiles;

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

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

    if(aConditionIsMet) {

        it = curFiles.erase(it);
    }
    else ++it;
}
//curFiles是:vectorcurFiles;
向量::迭代器it=curFiles.begin();
while(it!=curFiles.end()){
if(条件集){
它=curFiles.erase(它);
}
否则它;
}

如果有人需要处理索引

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);
    }
}
向量;
对于(int i=0;i-1&&i<(int)vector.size());
如果(向量[i]%3==0)
{
printf(“删除%d,%d\n”,向量[i],i);
vector.erase(vector.begin()+i);
}
if(size!=(int)vector.size())
{
--一,;
size=vector.size();
printf(“返回%d\n”,大小);
}
}

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

向量:迭代器 for(mit=myVec.begin();mit!=myVec.end();) {if(条件) mit=myVec.erase(mit); 其他的 麻省理工学院++; }
请参阅此相关问题:使用erase的返回值返回有效的迭代器。所以只需要将返回值赋给迭代器——这里没有性能问题。@harper:实际上,这里有一个很大的性能问题;从向量的中间删除一个项需要所有其他项向下移动,这涉及每次调用O(N)构造函数和析构函数?如何提高擦除性能?我只是注释了语句“迭代器失效..不管是哪种形式”…另外,为了缩小向量(就像OP想要做的那样),可以使用交换技巧。这里的详细信息:可以说
i=orbsList.erase(i)
而不是
orbsList.erase(i++)
我知道有点晚了,但你可能想看看这个。它与大多数人所期望的相反,但它来自C++的创造者,而在简单的情况下,优雅,我怀疑它在现实世界中的有效性。这对动态大小向量根本不起作用。“这对动态大小向量根本不起作用。”为什么不呢?虽然
std::remove_if
lambda看起来不错,但如果我只想删除一个与条件匹配的元素,它仍然会遍历每个元素直到最后。因此,我更喜欢手动迭代,这样我就可以随时从循环中中断。为什么不只是调整大小--I--然后删除?@user1122069我的良好实践禁止这样的事情,很多人不理解
--I
nad
I--
使用
*mit
访问迭代器位置的值
// curFiles is: vector < string > curFiles;

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

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

    if(aConditionIsMet) {

        it = curFiles.erase(it);
    }
    else ++it;
}
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);
    }
}
vector <cMyClass>::iterator mit
for(mit = myVec.begin(); mit != myVec.end(); )
{   if(condition)
        mit = myVec.erase(mit);
    else
        mit++;
}