这是从 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本身按照您的描述执行,将旧成员移动到向量的后面,并返回指向第一个无效成员的迭代器。传递此内容和向量对erase
的end()
允许擦除所有旧成员,因为它们位于连续块中。在您的方案中,您必须在调用 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 以检测任何隐藏的内存访问问题,或切换到智能指针。
相关文章:
- 在C++中初始化向量映射的最有效方法
- 将此布尔值传递给此函数的最有效方法是什么?
- 比较C++变量的最有效方法
- 在 c++ 中解决段树以外的范围查询的有效方法是什么?
- 存储变量的更有效方法是什么?
- 确保套装新鲜度的有效方法
- 当映射包含字符串向量作为值时,从值中获取键的有效方法
- 映射唯一值和重复值的有效方法.可以访问键或值的位置
- 在C++事务之间存储大量字符数据的有效方法
- 在unordered_multimap中精确迭代一次每个键的有效方法
- 一种将 Dart 中的字节数据转换为 C++ 中的无符号字符*的有效方法?
- 检查两个向量是否并行的最有效方法
- 从浮点数中删除小数部分但保留类型的有效方法
- 传递非泛型函数的最有效方法是什么?
- 按升序打印矢量的所有元素直到它为空而没有重复项的最有效方法是什么?
- 创建字符串数组的有效方法
- 返回一个引用C++中另一个类对象的对象的有效方法
- C++去除前x个元素的有效方法,在不改变向量大小的情况下将第x+1个元素推到第一个
- 将一种数据类型的向量复制到同一数据类型的结构向量中的有效方法是什么
- 从std::map值中获取密钥的有效方法