如何将所有指针从一个向量移动到另一向量?

时间:2018-08-08 09:40:44

标签: c++ performance c++11

基本上我想做的是删除向量中的一些指针,但是我发现在向量中间进行操作可能会很慢。

所以我有一个向量,里面已经有数据:

std::vector<Class*> vec1; // This already contains pointers

我将遍历vec1并将某些指针添加到另一个向量(vec2):vec2.push_back(vec1.at(index))

现在我想做的是类似vec1 = vec2的事情,但是我不知道这是否是一种更好的方法。

最好的方法是什么?

我尝试过:

  1. 在遍历vec1时,只是擦除了我需要从中删除的内容:

    it = vec1.erase(it)

  2. 在遍历vec1时,将最后一项移至实际索引并弹出popp_back

    vec1.at(index) = vec1.back(); vec1.pop_back();

  3. 在通过vec1而不是使用std::remove_if

    循环时,在指针指向的对象上设置一些属性

    vec1.erase(std::remove_if(vec1.begin(), vec1.end(), shouldBeRemoved), vec1.end());

  4. 现在,我试图在遍历vec1并添加要保留的指针的同时生成一个新向量,然后将该新向量的内容“交换”或“移动”到vec1。

显然,当以第四种方式进行操作时,指针会失效:(

我很想看看你们对我的建议。非常感谢愿意提供帮助的每个人!

3 个答案:

答案 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将遭受性能问题,因为它将保持您不删除的项目的顺序;这意味着您可以进行大量轮班以保持此顺序。

交换和弹出将遇到不需要反复弹出后部的问题-它可以调整向量的大小或执行其他操作。

这样,通过结合以下思想:交换“最后一个未被交换出去的”(即,第一次是最后一次,第二次是第二次,以此类推),然后在结束时擦除最终项目;您应该拥有最快的算法。

一些评论表明,副本比交换更快。而当进行单拷贝时为真;一个向量,当您多次复制多个元素时;交换将大大加快。