Wskaźnik do obiektu w dwóch kontenerach i usuwanie tego obiektu
Ostatnio zmodyfikowano 2013-09-03 13:44
Virpi Temat założony przez niniejszego użytkownika |
Wskaźnik do obiektu w dwóch kontenerach i usuwanie tego obiektu » 2013-09-01 20:54:28 Krótki i treściwy problem. W uproszczeniu, mam dwie klasy CGameObject i CFuel. CFuel dziedziczy po CGameObject. Mam w programie 2 kontenery: std::vector < CGameObject *> FGameObjects; std::vector < CFuel *> FFuel;
W pierwszym trzymam wszystkie obiekty typu CGameObject, bo przez polimorfizm rysuję je na ekranie, a w drugim tylko paliwa. Paliwa dodaję w programie tak: CFuel * paliwo = new CFuel( pos.first, pos.second, value ); FGameObjects.push_back( paliwo ); FFuel.push_back( paliwo );
W pewnym miejscu programu mogę usunąć obiekt CFuel, jeśli najechał na nie samochod: for( unsigned int i = 0; i < FFuel.size(); i++ ) { if( FFuel[ i ]->checkCollision( FCar ) ) { delete FFuel[ i ]; FFuel[ i ] = NULL; } }
A później jeszcze w tej samej pętli w grze mam rysowanie obiektów na ekranie: for( unsigned int i = 0; i < FGameObjects.size(); i++ ) { if( FGameObjects[ i ] != NULL ) FGameObjects[ i ]->draw( FGame->GameWindow ); }
I otrzymuję AccessViolation. Wydaje mi się, że jeżeli ustawiłem wcześniej po usunięci obiektu wartośc wskaźnika do niego na NULL, to to, na co wskazuje on będąc w drugim kontenerze też wynosi NULL, więc przy rysowaniu ten wskaźnik powinien zostać pominięty .... Czy dobrze to rozumiem? Jeśli nie, to jest jakiś sprytny sposób, na usunięcie tego wskaźnika z drugiego kontenera(nie wiedząc przecież, na jakiej jest on pozycji)? |
|
DejaVu |
» 2013-09-01 21:08:31 W grach najlepiej oznaczyć obiekt flagą, że ma on zostać zniszczony. Obiekty z ustawioną flagą 'zniszczony' pomijasz, a po wyświetleniu sceny i wykonaniu wszelkich innych algorytmów robisz dodatkową pętlę, która kasuje obiekty z ustawioną flagą 'zniszczony'.
/edit: Poza tym błędem u Ciebie jest to, że wpychasz do dwóch kontenerów jeden wskaźnik. Kasując obiekt w jednym kontenerze powinieneś również go skasować w drugim. W przeciwnym wypadku po wykonaniu operacji delete wszelkie zapisane wskaźniki na konkretny usunięty obiekt są nieprawidłowe i nie można się do nich odwoływać, a Ty temu obecnie nie zapobiegasz. |
|
DejaVu |
» 2013-09-01 21:13:30 Dodam jeszcze, że jeżeli masz potrzebę trzymania wskaźnika w kilku kontenerach to powinieneś użyć boost::shared_ptr lub std::shared_ptr (jeżeli używasz kompilatora i bibliotek dla C++11). |
|
b00rt00s |
» 2013-09-03 13:41:23 |
|
pekfos |
» 2013-09-03 13:44:20 Co do problemu: wystarczy, że usuniesz także wskaźnik z FGameObject. |
|
« 1 » |