4

这是我的代码,用于更新向量中的项目列表并删除其中一些:

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 无法向我显示这条线),所以我想确保这部分没问题。还是……?

更新:我发现了这个错误,确实它在我的代码的另一部分。

4

4 回答 4

3

是的,这是一种有效的方式。但是,如果它不是您程序中的性能瓶颈,那么最好使用智能指针来管理Particle对象的生命周期。

于 2012-12-04T10:30:24.223 回答
1

看看std::remove_if

此外,使用共享指针可能会很好,因为它可以让生活更轻松:-)

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() );
于 2012-12-04T10:37:05.860 回答
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;
    }
}

或者,更好的是,使用智能指针和擦除/删除习语。Remove_if 本身就像您描述的那样,将旧成员移动到向量的后面并返回一个指向第一个无效成员的迭代器。传递这个和向量的end()toerase允许擦除擦除所有旧成员,因为它们在一个连续的块中。在您的场景中,您必须在调用擦除之前删除每个:

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());

然后测试整个代码的性能并优化实际瓶颈所在的位置。

于 2012-12-04T11:04:08.473 回答
0

我在代码中看不到任何直接问题。您可能对向量内的实际指针有一些问题。

尝试在您的代码上运行 valgrind 以检测任何隐藏的内存访问问题,或切换到智能指针。

于 2012-12-04T10:24:18.333 回答