从向量中删除元素

3
在C++中,我该如何从向量中删除元素?
  1. 直接从当前位置删除,即让向量调整大小
  2. 将要删除的元素与最后一个元素交换,以便使用pop_back()(希望不需要复制所有内容...)
对于(1),我尝试了以下方法,但我不确定它是否按照预期执行(删除传递给removeItem()的项目),而且似乎不太优雅:
vector<Item*> items;            
// fill vector with lots of pointers to item objects (...)

void removeItem(Item * item) {
    // release item from memory
    if (int i = getItemIdIfExists(item) != -1) {
        items.erase (items.begin()+i);
    }
}

int getItemIdIfExists(Item * item) {
    // Get id of passed-in Item in collection
    for (unsigned int i=0; i<items.size(); i++) {
        // if match found
        if (items[i] == item)     return i;  
    }
    // if no match found
    return -1;
}
3个回答

8
标准的remove+erase惯用语通过值删除元素:
#include <vector>
#include <algorithm>

std::vector<int> v;
v.erase(std::remove(v.begin(), v.end(), 12), v.end());
remove 会重新排序容器中的元素,以便所有被删除的元素都在末尾,并返回一个指向被删除元素范围开头的迭代器;而 erase 则实际上从容器中删除元素。

如果您有多个具有相同值的元素需要一次性删除,则像 vector 这样的连续存储容器可以达到最高效率。


这不应该只是remove而不是v.remove吗? - Vlad

2
void removeItem(Item*item){
  for(int i=0; i<items.size(); i++){
    if (items[i]==item){
      swap(items[i], items.back());
      items.pop_back();
      return;
    }
  }
}

如果顺序无关紧要,为什么不使用 std::set 呢?

(虽然,如果顺序无关紧要,为什么不使用一个 std::set 呢?)

谢谢,那解决了我的问题。它也只删除一个元素(这就是我想要的)。我的代码似乎因某种原因删除了多个元素。关于集合,我不太确定为什么要使用它!除了这种特殊情况外,我的访问主要是顺序的(即所有项目都更新、所有项目都呈现等)。 - Ben
我不确定你是如何使用它的,所以我认为从集合中删除项比从向量中删除项更快(即使我们没有移动整个向量,对于我的removeItem来说仍然是O(n)),但如果你不进行太多的删除操作,你应该可以使用向量。 - Vlad
1
嗯,items是游戏中的可收集物品,因此它们会在每一帧顺序更新和渲染,而只有在玩家实际收集它们时才会被删除。因此,在这种情况下,我想向量是更好的选择。 - Ben

1

直接从原来的位置删除,即让向量调整大小

这就是“erase”命令所做的。

将要删除的元素与最后一个元素交换位置,以便使用pop_back()函数(希望它不需要复制周围所有内容……)

这正是“remove”命令所做的,除了它会保留剩余对象的顺序,所以确实需要复制周围的所有内容。

你所做的可以写成:

items.erase(
    std::remove(
        items.begin(), items.end()
      , item
    )
  , items.end()
);

和你的代码不同之处在于这个将会移除所有值为item的项,而不仅仅是第一个。


使用您的代码,我得到了以下错误:无法将'__gnu_cxx::__normal_iterator<Item **,std :: vector <Item *,std :: allocator <Item *> > >'转换为'int remove(const char *)'的参数1的'const char *' | - Ben
这并不是 remove 的作用。它涉及复制,因为它保持了剩余项目的顺序。 - UncleBens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接