我已经实现了基于位置的四叉树的SubDivide方法的一部分,如下所示:
//Give elements of mine to children, may or may not accept them.
for(std::size_t i = 0; i < MAX_CHILDREN; ++i) {
std::vector<T>::iterator b = _elements.begin();
std::vector<T>::iterator e = _elements.end();
for(std::vector<T>::iterator _iter = b; _iter != e; ++_iter) {
if(_children[i]->Add(*_iter)) continue;
}
}
这种方法的问题在于,当树细分时,父节点如果子节点接受它,则不会从其自己的容器中删除该元素,因此我将其更改为使用擦除增量惯用语:
//Give elements of mine to children, may or may not accept them.
for(std::size_t i = 0; i < MAX_CHILDREN; ++i) {
std::vector<T>::iterator b = _elements.begin();
for(std::vector<T>::iterator _iter = b; _iter != _elements.end(); /** DO NOTHING **/) {
if(_children[i]->Add(*_iter) == false) {
++_iter;
continue;
}
_elements.erase(_iter++);
}
}
但是,在子节点接受元素并且父节点从其容器中删除副本之后,对于for循环的条件检查,vector iterator not compatible
失败了。我怀疑通过擦除迭代器的迭代器是无效的(因为它们应该)但是我在其他地方有这个确切的代码(for循环中的条件是不同的,否则涉及迭代器的代码是相同的)并且它不会失败。 / p>
答案 0 :(得分:2)
关于std::vector
erase()
iterator erase(const_iterator position);
iterator erase(const_iterator first, const_iterator last);
(§23.3.6.5[vector.modifiers] / p3),标准可以这样说:
vector
效果:在点或之后使迭代器和引用无效 擦除。
因此,擦除增量根本不适用于erase()
s。 _iter = _elements.erase(_iter);
调用使递增的迭代器无效。请改用#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
int main(int argc, char* argv[])
{
std::vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(10);
v.push_back(40);
v.push_back(10);
v.push_back(60);
std::vector<int>::iterator b = v.begin();
for(std::vector<int>::iterator _iter = b; _iter != v.end(); /** DO NOTHING **/) {
if(*_iter != 10) {
++_iter;
continue;
}
_iter=v.erase(_iter); // v.erase(iter++) causes abort()
}
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
return 0;
}
。
测试代码 - 这在我的VS 2010上编译并运行良好:
{{1}}