Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Destruktory oraz usuwanie elementów z list

Ostatnio zmodyfikowano 2024-10-13 11:37
Autor Wiadomość
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.

C/C++
std::vector < GameObject * > gameObjects; // lista wszystkich obiektów różnych typów
std::vector < ItemOnMap * > itemsOnMap; // lista obiektów typu ItemOnMap
std::vector < Furniture * > furnitures; // lista obiektów typu Furniture
std::vector < Wall * > walls; // Lista obiektów typu Wall
std::vector < Building * > buildings; // Lista obiektów typu Building

C/C++
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 );
       
}
    }
}

C/C++
void clearAllMainListsOfGameObjects() {
   
// clear all main lists
    // usuwanie wszystkich obiektów
    /*
    for (auto& go : gameObjects)
        if (go!=nullptr) {
            delete go;
            go = nullptr;
        }
    */
   
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
P-181680
pekfos
» 2024-10-10 16:43:02
C/C++
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.
P-181681
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?
P-181682
pekfos
» 2024-10-11 06:15:27
C/C++
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 ); // new_items nie jest już potrzebne, więc lepiej jest przenieść zawartość niż kopiować
P-181683
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-11 06:18:34
Mi chat GPT napisał coś takiego :

C/C++
// delete items
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;
   
}
P-181684
pekfos
» 2024-10-11 06:26:13
Uhhhh... Chat GPT napisał iterowanie po wektorze w czasie kwadratowym.
P-181685
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.git

Jak zlokalizować kod odpowiedzialny za wczytywanie mapy:

MapEditor.hpp
C/C++
if( sf::Keyboard::isKeyPressed( sf::Keyboard::F6 ) ) {
   
mapa->load();
}

To błąd spowodowany przez funkcję w Mapa.hpp
C/C++
Chunk::~Chunk() {
   
delete terrain;
   
//clearLists();  // error
}

pogubiłem się w kodzie...
P-181686
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.

C/C++
void load( string filename = "world/world.txt" ) {
   
   
// clearing
   
for( auto & chunk: chunks ) {
       
delete chunk;
   
}
   
   
chunks.clear();
   
clearAllMainListsOfGameObjects();
   
// ...
}

Następnie zabieramy się za czyszczenie fragmentów mapy
C/C++
~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ę
C/C++
void clearAllMainListsOfGameObjects() {
   
// clear all main lists
   
   
for( auto & nature: natures ) {
       
auto it = std::find( natures.begin(), natures.end(), nature );
       
if( it != natures.end() ) {
           
natures.erase( it );
           
delete nature;
       
}
       
    }
   
   
natures.clear();
   
P-181687
« 1 » 2
  Strona 1 z 2 Następna strona