Vector.erase (Iterator) вызывает плохой доступ к памяти - PullRequest
4 голосов
/ 31 мая 2010

Я пытаюсь выполнить переупорядочение Z-индекса в videoObjects, хранящемся в vector. План состоит в том, чтобы определить videoObject, который будет помещен в первую позицию vector, стереть его и затем вставить в первую позицию. К сожалению, функция erase() всегда вызывает плохой доступ к памяти.

Вот мой код:

testApp.h:

vector<videoObject> videoObjects;
vector<videoObject>::iterator itVid;

testApp.cpp:

// Get the videoObject which relates to the user event
for(itVid = videoObjects.begin(); itVid != videoObjects.end(); ++itVid) {
  if(videoObjects.at(itVid - videoObjects.begin()).isInside(ofPoint(tcur.getX(), tcur.getY()))) {
   videoObjects.erase(itVid);
  }
}

Это должно быть так просто, но я просто не понимаю, где я делаю неправильный поворот.

Ответы [ 4 ]

15 голосов
/ 31 мая 2010

Вы должны сделать

itVid = videoObjects.erase(itVid);

Цитата из cplusplus.com :

[vector::erase] делает недействительными все итераторы и ссылки на элементы после position или first .

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

Обновление: способ доступа к текущему элементу внутри вашего состояния выглядит довольно странно. Также следует избегать увеличения итератора после erase, так как это пропустит элемент и может вызвать ошибки за пределами допустимого. Попробуйте это:

for(itVid = videoObjects.begin(); itVid != videoObjects.end(); ){
  if(itVid->isInside(ofPoint(tcur.getX(), tcur.getY()))){
    itVid = videoObjects.erase(itVid);
  } else {
    ++itVid;
  }
}
3 голосов
/ 31 мая 2010

Осторожно, удаление элементов по одному из вектора имеет квадратичную сложность. STL на помощь!

#include <algorithm>
#include <functional>

videoObjects.erase(
    std::remove_if(
        std::bind2nd(
            std::mem_fun_ref(&videoObject::isInside),
            ofPoint(tcur.getX(), tcur.getY())
        ),
    ),
    videoObjects.end()
);
1 голос
/ 31 мая 2010

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

0 голосов
/ 31 мая 2010

erase функция возвращает следующий действительный итератор.

Вам нужно будет сделать цикл while и сделать что-то вроде

iterator = erase(...)

с соответствующими проверками.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...