tBane Temat założony przez niniejszego użytkownika |
[C++] Destruktory oraz usuwanie elementów z list » 2024-10-10 10:39:06 Witam. Mam problem z destruktorami. Potrzebuję usunąć z list wszystkie obiekty. std::vector < GameObject * > gameObjects; std::vector < ItemOnMap * > itemsOnMap; std::vector < Furniture * > furnitures; std::vector < Wall * > walls; std::vector < Building * > buildings; class Building : public GameObject { public: sf::Vector2i size; std::vector < ItemOnMap * > _items; std::vector < Furniture * > _furnitures; std::vector < Wall * > _walls; Building() { ItemOnMap * item = new ItemOnMap( prefab, x, y ); _items.push_back( item ); } ~Building() { for( auto & item: _items ) { delete item; item = nullptr; } _items.clear(); std::vector < ItemOnMap * > new_items; for( auto & item: itemsOnMap ) if( item != nullptr ) new_items.push_back( item ); itemsOnMap = new_items; for( auto & furniture: _furnitures ) { delete furniture; furniture = nullptr; } _furnitures.clear(); std::vector < Furniture * > new_furnitures; for( auto & furniture: furnitures ) if( furniture != nullptr ) new_furnitures.push_back( furniture ); furnitures = new_furnitures; for( auto & wall: _walls ) { delete wall; wall = nullptr; } _walls.clear(); std::vector < Wall * > new_walls; for( auto & wall: walls ) if( wall != nullptr ) new_walls.push_back( wall ); walls = new_walls; std::vector < GameObject * > new_gameObjects; for( auto & go: gameObjects ) if( go != nullptr ) new_gameObjects.push_back( go ); gameObjects = new_gameObjects; } void addGameObjectsToMainLists() { for( auto & item: _items ) { itemsOnMap.push_back( item ); gameObjects.push_back( item ); } for( auto & furniture: _furnitures ) { furnitures.push_back( furniture ); gameObjects.push_back( furniture ); } for( auto & wall: _walls ) { walls.push_back( wall ); gameObjects.push_back( wall ); } } }
void clearAllMainListsOfGameObjects() { gameObjects.clear(); itemsOnMap.clear(); furnitures.clear(); walls.clear(); buildings.clear(); }
Exception thrown at 0x00007FF87EA758A4 (sfml-graphics-d-2.dll) in RPG.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF. Git jakby był potrzebny https://github.com/tBane1995/test.git |
|
pekfos |
» 2024-10-10 16:43:02 for( auto & item: _items ) { delete item; item = nullptr; } _items.clear();
std::vector < ItemOnMap * > new_items; for( auto & item: itemsOnMap ) if( item != nullptr ) new_items.push_back( item );
itemsOnMap = new_items; Wygląda jakbyś chciał z małej listy zniszczyć obiekty, a następnie usunąć wskaźniki na te obiekty z dużej listy itemsOnMap. Tylko to tak nie może zadziałać bo nadpisujesz zerem wskaźniki w małej liście i sprawdzasz czy w dużej się zmieniły, a tak wskaźnik akurat nie działa. Zamiast item != nullptr, wyszukaj wskaźnik w małej liście, np przez std::find(). Oczywiście, nie nadpisuj tych wskaźników przez tym krokiem. Mając n obiektów w małej liście i N>=n w dużej, takie rozwiązanie ma złożoność O(Nn), ale to nie powinien być problem dopóki nie będziesz miał na przykład n>1000. Zerowanie wskaźników i ręcznie opróżnianie kontenera w destruktorze są na ogół bezcelowe, bo kontener zostanie za chwilę i tak zniszczony, a zawarte w nim wskaźniki tym bardziej nie będą więcej używane. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-10 19:22:46 Wygląda jakbyś chciał z małej listy zniszczyć obiekty, a następnie usunąć wskaźniki na te obiekty z dużej listy itemsOnMap. Dokładnie tak. Tylko to tak nie może zadziałać bo nadpisujesz zerem wskaźniki w małej liście i sprawdzasz czy w dużej się zmieniły, a tak wskaźnik akurat nie działa. Zamiast item != nullptr, wyszukaj wskaźnik w małej liście, np przez std::find(). Czy mógłbym prosić o przykład na podstawie mojego kodu? |
|
pekfos |
» 2024-10-11 06:15:27 std::vector < ItemOnMap * > new_items; for( auto & item: itemsOnMap ) if( std::find( _items.begin(), _items.end(), item ) == _items.end() ) new_items.push_back( item );
for( auto & item: _items ) { delete item; } itemsOnMap = std::move( new_items ); |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-11 06:18:34 Mi chat GPT napisał coś takiego : for( auto it = _items.begin(); it != _items.end(); ) { auto item = * it; auto itItem = std::find( itemsOnMap.begin(), itemsOnMap.end(), item ); if( itItem != itemsOnMap.end() ) itemsOnMap.erase( itItem ); auto itGameObject = std::find( gameObjects.begin(), gameObjects.end(), item ); if( itGameObject != gameObjects.end() ) gameObjects.erase( itGameObject ); it = _items.erase( it ); delete item; }
|
|
pekfos |
» 2024-10-11 06:26:13 Uhhhh... Chat GPT napisał iterowanie po wektorze w czasie kwadratowym. |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-11 06:42:05 Teraz mam taki problem, że pamięć mi cieknie przy wczytywaniu mapy (Przy ciągłym naduszaniu F6). Wrzuciłem projekt na Git'a https://github.com/tBane1995/test.gitJak zlokalizować kod odpowiedzialny za wczytywanie mapy: MapEditor.hppif( sf::Keyboard::isKeyPressed( sf::Keyboard::F6 ) ) { mapa->load(); }
To błąd spowodowany przez funkcję w Mapa.hpp Chunk::~Chunk() { delete terrain; }
pogubiłem się w kodzie... |
|
tBane Temat założony przez niniejszego użytkownika |
» 2024-10-11 09:17:09 Zacznijmy jeszcze raz, bo się pogubiłem w tym wszystkim. Mam funkcję mapa->load(), która służy do wczytywania mapy. W tej funkcji chciałbym wyczyścić wszystkie listy przed załadowaniem nowej mapy. void load( string filename = "world/world.txt" ) { for( auto & chunk: chunks ) { delete chunk; } chunks.clear(); clearAllMainListsOfGameObjects(); }
Następnie zabieramy się za czyszczenie fragmentów mapy ~Chunk() { delete terrain; for( auto & n: _natures ) deleteGameObject( n ); }
void deleteGameObject( GameObject * object ) { if( object->type == gameObjectType::Nature ) { for( auto * nature: _natures ) { auto it = std::find( _natures.begin(), _natures.end(), nature ); if( it != _natures.end() ) { _natures.erase( it ); } } } delete object; }
I na końcu czyścimy główną listę void clearAllMainListsOfGameObjects() { for( auto & nature: natures ) { auto it = std::find( natures.begin(), natures.end(), nature ); if( it != natures.end() ) { natures.erase( it ); delete nature; } } natures.clear(); |
|
« 1 » 2 |