Usuwanie wybranego elementu std::map w pętli

0

Witam! Mam następujący problem z którym męczę się od kilku godzin i nie mogę znaleźć nigdzie odpowiedzi. Muszę wywołać funkcję release() usuwającą aktora ze sceny oraz usunąć element (klucz ?) który mu odpowiadał w std::map. Działa to poprawnie dopóki, dopóty do usunięcia pozostał ostatni element. Przykładowo dla 2 elementów:
partActors[0] -> (1, 0x00afbbf0)
partActors[1] -> (3,0x063ffc60)
Chce usunąć element o kluczu 3. Iterator itr ma prawidłową wartość którą przypisuje do toErase. Wszystko działa z wyjątkiem, że wykonuje się ++itr i itr przyjmuje losowe wartości (3452816845, 0xcdcdcdcd) (tak jakby wychodził poza zakres ?). Co prawda element (o kluczu 3) jest usunięty, ale dostaje komunikat w debugerze: First-chance exception at (0xjakiś adres)... i aplikacja się wiesza.

map<unsigned int, PxRigidActor*>::iterator itr = partActors.begin();
map<unsigned int, PxRigidActor*>::iterator toErase;
while(itr!=partActors.end())
	{
		if(checkisInside(*itr->second,itr->first)) //bool checkisInsideAndDelete(PxRigidActor &actor, unsigned int ID)
		{
			toErase = itr;
			++itr;
			toErase->second->release();
			partActors.erase(toErase);	
		}
		else
		{
			++itr;
		}
	}
2

Bo po prostu nie wolno ci tak zrobić. Nie możesz modyfikowac kolekcji po której właśnie iterujesz bo się zepsuje i tyle. Przepisuj do nowej kolekcji te "nie usunięte" elementy i tyle.

0

A tak próbowałeś:

map<unsigned int, PxRigidActor*>::iterator itr = partActors.begin();
while(itr!=partActors.end())
  {
   if(checkisInside(*itr->second,itr->first)) //bool checkisInsideAndDelete(PxRigidActor &actor, unsigned int ID)
     {
      map<unsigned int, PxRigidActor*>::iterator toErase=itr;
      toErase->second->release();
      partActors.erase(toErase,++itr);        
     }
   else ++itr;
  }
0
_13th_Dragon napisał(a):

A tak próbowałeś:

...
      partActors.erase(toErase,++itr);     
...   
  }

Nie działa.

Generalnie kod poniżej wykonuje się bez problemu tylko zależy mi, aby wywołać jeszcze funkcję release() dla konkretnego aktora.

map<unsigned int, PxRigidActor*>::iterator itr = partActors.begin();
while(itr!=partActors.end())
  {
   if(checkisInside(*itr->second,itr->first))
     {
      partActors.erase(itr++);        
     }
   else ++itr;
  }
1

To możesz oddzielić sprawdzenie od usuwania:

list<unsigned> drop;
for(map<unsigned int,PxRigidActor*>::iterator i=partActors.begin();i!=partActors.end();++i)
  {
   if(checkisInside(*i->second,i->first))
     {
      i->second->release();
      drop.push_back(i->first);
     }
  }
for(list<unsigned>::itrerator i=drop.begin();i!=drop.end();++i) partActors.erase(*i);
0

Usuwa elementy, ale przy kolejnym wywołaniu:

 for(list<unsigned>::iterator i=drop.begin();i!=drop.end();++i) partActors.erase(*i);

wypisuje: First-chance exception at 0x0103fd03 in app.exe: 0xC0000005: Access violation reading location 0xfeeeff6e.

1

Problem był ze wskaźnikiem gSelectedActor, który przechowywał adres do usuniętego aktora. Podczas usuwania nie sprawdzałem czy zaznaczono aktora. W pętli renderingu cały czas gSelectedActor próbował pobrać nazwę i pozycję usuniętego aktora, stąd błąd. Pierwsze moje rozwiązanie również działa.

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