C++ 基于条件语句删除循环中的向量元素
在这个代码段中,Update()返回一个布尔值,如果它返回false,我想从向量中删除元素 但是,这会产生调试断言失败的运行时错误。表达式为“向量迭代器不可递增” 代码:C++ 基于条件语句删除循环中的向量元素,c++,vector,iterator,C++,Vector,Iterator,在这个代码段中,Update()返回一个布尔值,如果它返回false,我想从向量中删除元素 但是,这会产生调试断言失败的运行时错误。表达式为“向量迭代器不可递增” 代码: for(auto iter = someVector.begin(); iter != someVector.end(); ++iter){ if(!iter->get()->Update()) iter = someVector.erase(iter); } for(auto iter = partic
for(auto iter = someVector.begin(); iter != someVector.end(); ++iter){
if(!iter->get()->Update()) iter = someVector.erase(iter);
}
for(auto iter = particles.begin(); iter != particles.end(); ++iter){
if(!iter->get()->Update()) iter = --(particles.erase(iter));
}
我也尝试过从迭代器中进行减法,如下所示:
for(auto iter = someVector.begin(); iter != someVector.end(); ++iter){
if(!iter->get()->Update()) iter = someVector.erase(iter);
}
for(auto iter = particles.begin(); iter != particles.end(); ++iter){
if(!iter->get()->Update()) iter = --(particles.erase(iter));
}
…但这会导致“向量迭代器不可递减”
如何使代码按预期工作;因此,当Update()函数返回false时,向量元素被删除?将循环更改为:
for(auto iter = someVector.begin(); iter != someVector.end();){
if(!iter->get()->Update())
iter = someVector.erase(iter);
else
++it;
}
断言的原因是,在调用
erase
之后,iter
可能等于end()
。“擦除”返回的迭代器已经是“下一个”,您不应该增加它。将循环更改为:
for(auto iter = someVector.begin(); iter != someVector.end();){
if(!iter->get()->Update())
iter = someVector.erase(iter);
else
++it;
}
断言的原因是,在调用
erase
之后,iter
可能等于end()
。erase
返回的迭代器已经是“下一个”,您不应该增加它。我建议不要像上面一样使用erase()
,而是像这样使用它:
someVector.erase(std::remove_if(someVector.begin(), someVector.end(),
[](decltype(*someVector.begin()) element){
return !element.get()->update();
},
someVector.end());
当只需要擦除一个元素时,它的作用与使用一个迭代器版本的
erase()
大致相同。当需要擦除多个元素时,复制/移动的次数会减少。请注意,我使用lambda函数只是因为它更容易表达,但如果lambda函数不可用,也可以使用合适的函数对象来表达。我建议不要使用首先使用擦除()
,而是像这样使用它:
someVector.erase(std::remove_if(someVector.begin(), someVector.end(),
[](decltype(*someVector.begin()) element){
return !element.get()->update();
},
someVector.end());
当只需要擦除一个元素时,它的作用与使用一个迭代器版本的
erase()
大致相同。当需要擦除多个元素时,复制/移动的次数会减少。请注意,我使用lambda函数只是因为它更容易表达,但如果lambda函数不可用,也可以使用合适的函数对象来表达。可能重复+1的可能重复我只写了这个:D,应该是return!element.get()->update()
谢谢,知道解决问题的多种方法总是很好的。然而,在我的情况下,我很少需要一次擦除超过1个元素。@JoshuaGerrard:使用该算法并不比单独擦除一个元素差,而且在有超过1个元素的罕见情况下效果更好。因此,这显然是要走的路!更不用说,这些算法可能会带来一些额外的性能改进(例如,适当的循环展开、在调试实现中只进行一次边界检查等):使用std::remove_if()
是一个胜利!再次感谢!我将进一步研究它,因为语法在我看来相当混乱。如果我能理解发生了什么,我会用它。是[](decltype…把我抛到了脑后。也就是说…谷歌是我的朋友;)@JoshuaGerrard:这只是一个C++11 lambda函数,使用decltype()
来确定参数类型有点笨拙。您还可以使用函数对象,如struct predict{template bool operator()(T&o){return!o.get()->Update();}代码>然后使用谓词()
。如果不需要通过get()。使用std::bind()
来编写东西也可以,但可能会更加混乱…+1我只写了这个:D,应该是return!element.get()->update()
谢谢,知道解决问题的多种方法总是很好的。然而,在我的情况下,我很少需要一次擦除超过1个元素。@JoshuaGerrard:使用该算法并不比单独擦除一个元素差,而且在有超过1个元素的罕见情况下效果更好。因此,这显然是要走的路!更不用说,这些算法可能会带来一些额外的性能改进(例如,适当的循环展开、在调试实现中只进行一次边界检查等):使用std::remove_if()
是一个胜利!再次感谢!我将进一步研究它,因为语法在我看来相当混乱。如果我能理解发生了什么,我会用它。是[](decltype…把我抛到了脑后。也就是说…谷歌是我的朋友;)@JoshuaGerrard:这只是一个C++11 lambda函数,使用decltype()
来确定参数类型有点笨拙。您还可以使用函数对象,如struct predict{template bool operator()(T&o){return!o.get()->Update();}代码>然后使用谓词()
。如果不需要通过get()。使用std::bind()
来编写东西也可以,但可能会更加混乱……这非常好,谢谢!我不知道你也可以省略for循环的最后一部分。没问题。也一定要读@Dietmar的答案!至于循环,您可以省略所有三条语句:for(;;){}
。这就是一些人喜欢写无限循环的方式。我觉得自己受过教育!再次谢谢你。这个很好用,谢谢你!我不知道你也可以省略for循环的最后一部分。没问题。也一定要读@Dietmar的答案!至于循环,您可以省略所有三条语句:for(;;){}
。这就是一些人喜欢写无限循环的方式。我觉得自己受过教育!再次感谢你。