Удалить элемент из вектора, используя ключевое слово this

Достаточно простой вопрос.

У меня есть объект Bullet, где в какой-то момент, когда пуля сталкивается с объектом, он уничтожается и удаляется из вектора Bullets.

Каждый объект Bullet имеет ссылку на вектор/список маркеров.

Как удалить его с помощью ключевого слова this внутри класса Bullet, когда это произойдет?

void collide(){
    //error C2678: binary '==': no operator found which takes a left-hand operand of type 'Bullet'
    //(or there is no acceptable conversion)
    bullets->erase(std::remove(bullets->begin(), bullets->end(), *this), bullets->end());
}

Так что да, этот код дает мне странную ошибку. Мне нужно знать, как это сделать, не перебирая вектор пуль с помощью цикла while/for и просто используя векторные функции. Очевидно, что текущий метод не работает, поскольку он выдает ошибку, указанную в коде.

Я также пытался использовать find() вместо remove(), та же ошибка.


person Joe Bid    schedule 26.01.2015    source источник
comment
У вас есть оператор равенства (т.е. operator==) для класса Bullet?   -  person Some programmer dude    schedule 26.01.2015
comment
Сообщение об ошибке едва ли могло быть яснее. И std::remove действительно выполняет итерацию по вектору, так что имейте в виду, что этот подход имеет линейную стоимость в любом случае.   -  person Kerrek SB    schedule 26.01.2015
comment
У меня его нет, но я действительно мог бы использовать решение. Я видел здесь другие примеры, которым не нужно было реализовывать оператор ==, но они все еще работали с этим методом. Честно говоря, как мне удалить элемент (это) из вектора?   -  person Joe Bid    schedule 26.01.2015
comment
Вы должны реализовать ‹code›operator==‹/code› или попробовать использовать std::remove_if с лямбдой для сравнения. Например: stackoverflow.com/questions/24086717/   -  person SGrebenkin    schedule 26.01.2015
comment
@JoeBid В этих примерах использовался вектор чего-то, что имело оператор равенства (целые числа, указатели, std::strings...). Обойти это требование невозможно.   -  person molbdnilo    schedule 26.01.2015
comment
Что-то в вашем Bullet не позволяет компилятору генерировать operator== автоматически. Должно быть очевидно, что такие функции, как find и remove, должны иметь возможность проверять, равен ли Bullet тому, который вы находите или удаляете. Поэтому вы должны это реализовать.   -  person Drew Dormann    schedule 26.01.2015
comment
Вместо того, чтобы прогонять массив каждый раз, когда удаляется маркер, может быть быстрее пометить маркеры как удаленные с помощью некоторого флага и, если у вас есть другая функция, которая обрабатывает список маркеров, добавьте туда код, чтобы стереть те, которые помечены для удаления. Таким образом, вы можете выполнить итерацию по вектору один раз, чтобы стереть много маркеров.   -  person Galik    schedule 26.01.2015


Ответы (3)


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

    for (Bullet& bullet : bullets){
        if (&bullet == this){
          bullets.erase(bullet);
            break;
         }
     }
person David Haim    schedule 26.01.2015
comment
Это небезопасно. Vector перераспределяет свое содержимое при стирании, поэтому итератор становится недействительным. Объяснено здесь stackoverflow.com/questions/10360461/ - person SGrebenkin; 26.01.2015

Попробуй это:

std::remove_if( bullets.begin(), bullets.end(), 
   [this] (const Bullet& s) {
      if (&s == this)
          return true;
      return false;
   }
);
person Serebrov    schedule 26.01.2015

Вам нужно получить итератор для объекта, который вы хотите стереть. Вы можете получить его, используя разницу между первым и текущим объектом:

bullets->erase(bullets->begin() + (this - &bullets.front()));

Обратите внимание, что это уничтожит объект, чей метод вы выполняете в данный момент, т. е. впоследствии вы не сможете получить доступ ни к одному из объектов-членов.

person Dietmar Kühl    schedule 26.01.2015