这是我的代码,用于更新向量中的项目列表并删除其中的一些项目:
std::vector<Particle*> particles;
...
int i = 0;
while ( i < particles.size() ) {
bool shouldRemove = particles[ i ]->update();
if ( shouldRemove ) {
delete particles[ i ];
particles[ i ] = particles.back();
particles.pop_back();
} else {
i++;
}
}
当我找到应该删除的项目时,我将其替换为向量中的最后一项,以避免可能多次复制其余的后备阵列。是的,我知道这是不成熟的优化......
这是从向量中删除项目的有效方法吗?我偶尔会在这个区域附近碰到一些(!)崩溃但是无法准确跟踪它们(LLDB没有向我显示该行),所以我想确保这部分没问题。或者是......?
更新:我发现了这个错误,实际上它是我代码的另一部分。
答案 0 :(得分:3)
是的,这是有效方式。但如果它不是程序中的性能瓶颈,那么最好使用智能指针来管理Particle
对象的生命周期。
答案 1 :(得分:1)
此外,使用共享指针可能会更好,因为它可以使生活更轻松: - )
typedef std::shared_ptr< Particle > ParticlePtr;
auto newend = std::remove_if( particles.begin(), particles.end(), [](ParticlePtr p) {return p->update();} );
particles.erase( newend, particles.end() );
答案 2 :(得分:1)
你正在迭代STL向量,所以使用迭代器,它就是它们的用途。
std::vector<Particle*>::iterator particle = particles.begin();
while ( particle != particles.end() ) {
bool shouldRemove = particle->update();
if ( shouldRemove ) {
particle = particles.remove(particle); //remove returns the new next particle
} else {
++particle;
}
}
或者,更好的是,使用智能指针和erase/remove idiom。 Remove_if本身就像你描述的那样,将旧成员移动到向量的后面并返回指向第一个无效成员的迭代器。将此向量和end()
传递给erase
允许擦除擦除所有旧成员,因为它们位于连续的块中。在您的方案中,您必须在调用erase之前删除每个:
auto deleteBegin = std::remove_if(
particles.begin(), particles.end(),
[](Particle* part){ return part->update();}));
for(auto deleteIt = deleteBegin; deleteIt != particles.end(); ++deleteIt)
delete *deleteIt;
std::erase(deleteBegin, particles.end());
或预C ++ 11:
bool ShouldDelete(Particle* part) {
return part->update();
}
typedef vector<Particle*> ParticlesPtrVec;
ParticlesPtrVec::iterator deleteBegin = std::remove_if(
particles.begin(), particles.end(), ShouldDelete);
for(ParticlesPtrVec::iterator deleteIt = deleteBegin;
deleteIt != particles.end(); ++deleteIt)
delete *deleteIt;
std::erase(deleteBegin, particles.end());
然后测试整个代码的性能并优化实际瓶颈的位置。
答案 3 :(得分:0)
我在代码中没有看到任何直接问题。你可能在向量中的实际指针有一些问题。
尝试在代码上运行valgrind以检测任何隐藏的内存访问问题,或切换到智能指针。