C++ 如何在C++;?
我基本上是循环检查所有条目,以检查是否要删除某些条目,但似乎以错误的方式:C++ 如何在C++;?,c++,windows,vector,C++,Windows,Vector,我基本上是循环检查所有条目,以检查是否要删除某些条目,但似乎以错误的方式: std::vector<HANDLE> myvector; for(unsigned int i = 0; i < myvector.size(); i++) { if(...) myvector.erase(myvector.begin()+i); } std::vector myvector; for(无符号整数i=0;i返回一个新的(有效)迭代器到被删除元素之后的下一
std::vector<HANDLE> myvector;
for(unsigned int i = 0; i < myvector.size(); i++)
{
if(...)
myvector.erase(myvector.begin()+i);
}
std::vector myvector;
for(无符号整数i=0;i
有人发现了其中的问题吗?如何正确操作?您可以使用
std::remove\u(如果
)。这将把所有剩余的元素移到前面,并将迭代器返回到新的后面。然后可以删除它:
struct my_predicate
{
bool operator()(HANDLE) const
{
return ...;
}
};
typedef std::vector<HANDLE> vector_type;
vector_type::iterator newEnd =
std::remove_if(myvector.begin(), myvector.end(), my_predicate());
myvector.erase(newEnd, myvector.end());
保持谓词的局部性
如果你觉得这很难看,那就收起它:
template <typename Vec, typename Pred>
Pred erase_if(Vec& pVec, Pred pPred)
{
pVec.erase(std::remove_if(pVec.begin(), pVec.end(),
pPred), pVec.end());
return pPred;
}
当然,C++0x lambda的工作是相同的。您应该使用向量迭代器进行此操作,并且,在删除时,为迭代器分配由
erase()返回的值。
你的问题是算法问题。如果两个相邻元素满足删除标准,会发生什么情况?第一个将被删除,但由于循环每次迭代后
i
都会递增,因此第二个将被跳过。这是因为向量在内存中是连续的,删除后的所有元素都向前移动一个索引
一个丑陋的黑客会做以下事情:
std::vector<HANDLE> myvector;
for(unsigned int i = 0; i < myvector.size();)
{
if(...)
myvector.erase(myvector.begin()+i);
else
i++;
}
std::vector myvector;
for(无符号整数i=0;i
我不确定使用迭代器是否有效,因为调用erase
会使迭代器对已擦除元素之后的元素无效
正如格曼所建议的,优雅的解决方案是使用。这将抽象出两件事:
编辑:我还应该补充一点,在最坏的情况下,被黑客攻击的解决方案是O(n2)。GMan的解决方案是O(n),假设您的移除条件是O(1)。我强烈鼓励您学习和使用GMan的解决方案。也许是另一个黑客解决方案
std::vector<HANDLE> myvector;
for(unsigned int i = myvector.size()-1; i >=0; --i)
{
if(...)
myvector.erase(myvector.begin()+i);
}
std::vector myvector;
for(unsigned int i=myvector.size()-1;i>=0;--i)
{
如果(…)
myvector.erase(myvector.begin()+i);
}
但至少它很简单。这似乎是最简单的解决方案,但我不确定它是否真的有效?我猜删除条目后的一个条目将被
it++
跳过。这是一个轻微的错误,当if为真时,您不需要执行it++
(否则,您可以跳过一个元素,或者更糟的是,您可以跳过end()
。最好是这样:for(it=v.begin();it!=v.end();){如果(…)it=v.erase(it);else++it;}
还值得注意的是,这在算法上很糟糕,因为erase
将导致以下所有元素被删除“向下移动一个”remove\u if/erase习惯用法更好,因为它避免了这种情况。是的,都是真的。感谢您的评论。现在将添加“continue”,并向下移动增量。还可以将if(…)
替换为while(…),只要条件还可以判断它是否在向量的末尾。我不太理解GMan的解决方案,所以我接受这个黑客版本。@用户:您应该请求澄清和/或教你C++。BTW:<代码> EraseE.()/代码>返回一个新的(有效)迭代器到被删除元素之后的下一个元素。@sth我明白了,你是对的。Ivan编辑的解决方案使用了这个事实。
for (it = myvector.begin(); it != myvector.end();) {
if (...) {
it = myvector.erase(it);
continue;
}
++it;
}
std::vector<HANDLE> myvector;
for(unsigned int i = 0; i < myvector.size();)
{
if(...)
myvector.erase(myvector.begin()+i);
else
i++;
}
std::vector<HANDLE> myvector;
for(unsigned int i = myvector.size()-1; i >=0; --i)
{
if(...)
myvector.erase(myvector.begin()+i);
}