基本上我想做的是删除向量中的一些指针,但是我发现在向量中间进行操作可能会很慢。
所以我有一个向量,里面已经有数据:
std::vector<Class*> vec1; // This already contains pointers
我将遍历vec1并将某些指针添加到另一个向量(vec2):vec2.push_back(vec1.at(index))
现在我想做的是类似vec1 = vec2
的事情,但是我不知道这是否是一种更好的方法。
最好的方法是什么?
我尝试过:
在遍历vec1时,只是擦除了我需要从中删除的内容:
it = vec1.erase(it)
在遍历vec1时,将最后一项移至实际索引并弹出popp_back
vec1.at(index) = vec1.back();
vec1.pop_back();
在通过vec1而不是使用std::remove_if
vec1.erase(std::remove_if(vec1.begin(), vec1.end(), shouldBeRemoved), vec1.end());
现在,我试图在遍历vec1并添加要保留的指针的同时生成一个新向量,然后将该新向量的内容“交换”或“移动”到vec1。
显然,当以第四种方式进行操作时,指针会失效:(
我很想看看你们对我的建议。非常感谢愿意提供帮助的每个人!
答案 0 :(得分:4)
您可以只使用std::remove_if
从向量中有条件地删除项目。该算法会将需要保留的项目转移到最前面。继续进行std::vector::erase
调用,以实际删除未移到最前面的项目。
这与您的选项3相似,但是您不需要首先设置属性-只需使用一个谓词来确定是否应保留该项目,并且避免两次跳过向量。
如果您不想就地执行此操作,但想填充一个新向量,那么std::copy_if
会这样做。
答案 1 :(得分:3)
从向量中删除内容应使用erase remove idiom
这里很好地介绍了:https://en.wikipedia.org/wiki/Erase%E2%80%93remove_idiom
基本思想是先移动元素,然后擦除不需要的项目,这比擦除和移动每个单独的元素要快,这是通过示例完成的:
v.erase( std::remove( v.begin(), v.end(), 5 ), v.end() );
但是一般来说:如果算法中有很多添加/删除步骤,则应使用std :: list,其中删除中间的元素要便宜得多。
答案 2 :(得分:1)
您的尝试2表明您对元素的顺序不感兴趣。 remove_if将遭受性能问题,因为它将保持您不删除的项目的顺序;这意味着您可以进行大量轮班以保持此顺序。
交换和弹出将遇到不需要反复弹出后部的问题-它可以调整向量的大小或执行其他操作。
这样,通过结合以下思想:交换“最后一个未被交换出去的”(即,第一次是最后一次,第二次是第二次,以此类推),然后在结束时擦除最终项目;您应该拥有最快的算法。
一些评论表明,副本比交换更快。而当进行单拷贝时为真;一个向量,当您多次复制多个元素时;交换将大大加快。