Стирание элемента из вектора - PullRequest
3 голосов
/ 24 октября 2011

Как в C ++ удалить элемент из вектора?

  1. Удалить его там, где он есть, т. Е. Позволить размеру вектора
  2. Поменять элемент, который нужно удалитьс последним элементом можно использовать st 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 голосов
/ 24 октября 2011

Стандартная метод удаления + стирания удаляет элементы по значению:

#include <vector>
#include <algorithm>

std::vector<int> v;
v.erase(std::remove(v.begin(), v.end(), 12), v.end());

remove переупорядочивает элементы так, чтобы все стирания были в конце, и возвращает итераторначало диапазона стирания, и erase фактически удаляет элементы из контейнера.

Это так же эффективно, как вы можете получить с контейнером непрерывного хранения, таким как vector, особенно если у вас есть несколько элементовто же значение, которое стирается за одну стирку.

2 голосов
/ 24 октября 2011
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?

1 голос
/ 24 октября 2011

Удалите его прямо из того места, где оно есть, т.е. пусть вектор изменит размер

Вот что делает erase.

Поменяйте местами удаляемый элемент с последним элементом s.t. Можно использовать pop_back () (который, я надеюсь, не требует копирования всего вокруг ...)

Это то, что делает remove, за исключением того, что оно сохраняет порядок оставшихся объектов, поэтому включает копирование всего вокруг.

То, что вы сделали, можно записать так:

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

Разница в вашем коде в том, что он фактически удалит все предметов стоимостью item, а не только первый.

...