繁体   English   中英

这是从std :: vector中删除项目的有效方法吗?

[英]Is this a valid way of removing items from of std::vector?

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

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没有向我显示该行),所以我想确保这部分没问题。 还是......?

更新:我发现了错误,实际上它是我的代码的另一部分。

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

看一下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() );

你正在迭代一个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()传递给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());

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM