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
nadI--
使用*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++;
}