Bład przy usuwniu iteratora metoda remove_if

0

Witam, od jakiegos pisze na iOS w cocos2dx i mam problem przy usuwaniu elementow z kontenera vector.

Jesli bedzie potrzeba wkleje wieksza ilosc kodu, na razie postaram sie wyjasnic o co chodzi. Nie jest to sprawa zycia i smierci bo juz rozwialem moj problem usuwania elementu w latwiejszy sposob, ale zaciekawilo mnie dlaczego ten kod powodowal blad... moze ktos bedzie potrafil to wytlumaczyc ;)

std::vector <std::shared_ptr <Potworek>> przeciwnicy; 

w tej tablicy 'przeciwnicy' przechowuje rozne rodzaje potworkow. Kazdy klasa tych potworkow zawiera jakies sprajty i inne [CIACH!], ale to nie jest wazne

Moja funkcja usuwajaca wyglada tak:
Gdzie tag_a i tag_b oznaczaja po prostu tagi do zderzajacych sie ze soba obiektow:

std::vector<std::shared_ptr <Potworek> >::iterator iterat;
iterat = std::remove_if(przeciwnicy.begin(), przeciwnicy.end(), SPRAWDZAMY(tag_a,tag_b));
przeciwnicy.erase(iterat, przeciwnicy.end());

Obiekt funkcji SPRAWDZAMY:

 
struct SPRAWDZAMY
{
    int taga;
    int tagb;
    
    SPRAWDZAMY(int a, int b)
    {
        taga = a;
        tagb = b;
    }
    
    bool operator()(const std::shared_ptr<Potworek> & x)
    {
        return ((taga==x->moj_sprajta()->getTag()) || (tagb==x->moj_sprajta()->getTag()));
    }
    
};

Jesli tagi zgadzaja sie z jakims konkretnym elementem w kontenerze przeciwnicy, ten element powinien zostac usuniety.

Ale tak na prawde nic sie nie dzieje. Nic nie jest usuwane, chociaz caly kod dziala poprawnie.

Kiedy zamienie ta linijke
przeciwnicy.erase(iterat, przeciwnicy.end());

na
przeciwnicy.erase(iterat);

Element zostaje usuniety, wszystko pieknie, ale zaraz po tym wyrzuca error:

template<class _Tp>
shared_ptr<_Tp>::~shared_ptr()
{
if (_cntrl)
_cntrl->__release_shared();
}

Wszystko zaczyna dzialac gdy zamienie ta linijke na:
przeciwnicy.erase(iterat-1);

Ale wtedy gdy przeciwnikow na ekranie jest wiecej jak 2 (czyli 3,4 itd..) usuwany jest nie ten potworek co trzeba ;)

Wszystko wyglada na to jakby ten iterator wychodzil poza zakres kontenera, co jest bardzo dziwne. Nie wiem dlaczego tak sie dzieje i czy rzeczywiscie o to chodzi...

Macie jakies pomysly co to moze byc?

0

złap to debuggerem i zobacz co siedzi pod tym iteratorem

0

http://en.cppreference.com/w/cpp/algorithm/remove

Używasz poprawnie, więc najprawdopodobniej Twój predykat jest słaby i nie zwraca true dla żadnego elementu, więc remove_if zwraca end. przeciwnicy.erase(end, przeciwnicy.end()) jest poprawnym wywołaniem, które nic nie robi. przeciwnicy.erase(end) nie jest poprawnym wywołaniem, bo próbuje dereferencji iteratora niewskazującego na żaden element, dlatego Ci się wywala. przeciwnicy.erase(end-1) po prostu usuwa ostatni element - nic dziwnego, że się nie sypie i kasuje "złego" przeciwnika.

0

Masz racje, blad byl w SPRAWDZAMY, a konkretniej w funkcji zwroc_sprajta(), ktora nie zwracala wskaznika, tylko robila kopie... Dzieki wielkie

1 użytkowników online, w tym zalogowanych: 0, gości: 1