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:39
Autor Wiadomość
pekfos
» 2024-10-11 16:23:16
C/C++
for( auto & nature: natures ) {
   
auto it = std::find( natures.begin(), natures.end(), nature );
   
if( it != natures.end() ) {
       
natures.erase( it );
       
delete nature;
   
}
   
}

natures.clear();
Ten kod nie ma sensu. Wyszukujesz obiekt w kontenerze, z którego go wziąłeś, więc warunek jest zawsze prawdziwy. Wywołanie erase() jest tu błędne, bo sprawia że pomijasz w pętli następny obiekt. Wywołanie clear() na końcu jest wystarczające, szybsze i nie interferuje z pętlą. Powinno być
C/C++
for( auto & nature: natures )
   
 delete nature;

natures.clear();
Analogiczna sytuacja ma miejsce w ~Chunk() i deleteGameObject(). Usuwanie elementów z kontenera po którym iterujesz wymaga uważnej implementacji:
C/C++
for( auto it = v.begin(); it != v.end(); ) {
   
if( deleteItem )
       
 it = v.erase( it );
   
else
       
 ++it;
   
}
Przykładowo jak masz elementy o indeksach 0, 1, 2, 3, 4 i chcesz usunąć 2, to pętla powinna odwiedzić indeksy 0, 1, 2, 2, 3. Bo gdy usuniesz element pod indeksem 2, to element pod starym indeksem 3 staje się elementem o indeksie 2. Jeśli polecisz naiwnie indeksy od 0 do rozmiaru minus jeden, to odwiedzisz 4 elementy zamiast pięciu.
P-181688
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-12 03:56:07
Czyli, że jak. To jest wystarczające ? Zlokalizowałem gdzie mi pamięć cieknie.
C/C++
void load( string filename = "world/world.txt" ) {
   
   
// clearing chunks
   
for( auto & chunk: chunks ) {
       
       
delete chunk;
   
}
   
   
chunks.clear();
   
   
// delete all GameObjects
   
for( auto & go: gameObjects )
       
 delete go;
   
   
gameObjects.clear();
   
natures.clear();
   
itemsOnMap.clear();
   
inventoriesOnMap.clear();
   
paths.clear();
   
monsters.clear();
   
furnitures.clear();
   
walls.clear();
   
characters.clear();
   
buildings.clear();
   
   
// dalsze wczytywanie
   
}

C/C++
if( objectType == "Chunk" ) {
   
   
short x, y;
   
string temp;
   
   
getline( lineStream, temp, '=' ); // wczytaj do "y="
   
lineStream >> y;
   
   
getline( lineStream, temp, '=' ); // wczytaj do "x="
   
lineStream >> x;
   
   
chunk = getChunk( x, y );
   
   
// load tiles
   
short value;
   
for( short y = 0; y < 16; y++ ) {
       
for( short x = 0; x < 16; x++ ) {
           
file >> value;
           
chunk->terrain->edit( x, y, value );
       
}
    }
   
}
else if( chunk != nullptr ) {
   
   
short x, y;
   
string temp;
   
string objectName;
   
   
getline( lineStream, temp, '"' ); // get string to temp to sign "
   
getline( lineStream, objectName, '"' ); // get string to objectName to sign "
   
getline( lineStream, temp, '=' ); // get string to temp to sign =
   
lineStream >> y; // string to y
   
getline( lineStream, temp, '=' ); // get string to temp to sign =
   
lineStream >> x; // string to x
   
cout << objectType << " \"" << objectName << "\" " << x << " " << y << "\n";
   
   
// tu mi pamięć cieknie
   
if( objectType == "Character" ) {
       
Character * character = new Character( getPrefab( objectName ), x, y );
       
chunk->_characters.push_back( character );
   
}
   
//
   
   
if( objectType == "Nature" ) {
       
Nature * nature = new Nature( getPrefab( objectName ), x, y );
       
chunk->_natures.push_back( nature );
   
}
   
P-181689
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-12 04:14:15
Tak jak wcześniej pisałem, pamięć cieknie dla obiektów typu "Character". Może źle je usuwam ?

C/C++
class Character
    : public Unit
{
public:
   
   
// EQUIPMENT
   
Item * helmet;
   
Item * armor;
   
Item * pants;
   
Item * leftHand;
   
Item * rightHand;
   
   
// HELMET - textures
   
Texture * helmetIdleTextures[ 16 ];
   
Texture * helmetRunTextures[ 16 ];
   
Texture * helmetAttackTextures[ 16 ];
   
   
// ARMOR - textures
   
Texture * armorIdleTextures[ 16 ];
   
Texture * armorRunTextures[ 16 ];
   
Texture * armorAttackTextures[ 16 ];
   
   
// PANTS - textures
   
Texture * pantsIdleTextures[ 16 ];
   
Texture * pantsRunTextures[ 16 ];
   
Texture * pantsAttackTextures[ 16 ];
   
   
// LEFT HAND - textures
   
Texture * leftHandIdleTextures[ 16 ];
   
Texture * leftHandRunTextures[ 16 ];
   
Texture * leftHandAttackTextures[ 16 ];
   
   
// RIGHT HAND - textures
   
Texture * rightHandIdleTextures[ 16 ];
   
Texture * rightHandRunTextures[ 16 ];
   
Texture * rightHandAttackTextures[ 16 ];
   
   
// SPRITES
   
sf::Sprite helmetSprite;
   
sf::Sprite armorSprite;
   
sf::Sprite pantsSprite;
   
sf::Sprite leftHandSprite;
   
sf::Sprite rightHandSprite;
   
   
Dialogue * dialogue;
   
   
Texture * talkWithTexture;
   
sf::Sprite talkWithSprite;
   
bool showHand;
   
   
   
Character( string name, string bodySet = "sets/body/hero" )
        :
Unit( name, bodySet, 36, 18, 64 )
   
{
       
       
type = gameObjectType::Character;
       
       
helmet = nullptr;
       
armor = nullptr;
       
pants = nullptr;
       
leftHand = nullptr;
       
rightHand = nullptr;
       
       
loadBody();
       
loadHelmet();
       
loadArmor();
       
loadPants();
       
loadLeftHand();
       
loadRightHand();
       
       
dialogue = nullptr;
       
       
talkWithTexture = getTexture( "GUI/talk" );
       
talkWithSprite = sf::Sprite();
       
talkWithSprite.setTexture( * talkWithTexture->texture );
       
talkWithSprite.setOrigin( talkWithTexture->cx, talkWithTexture->cy );
       
showHand = false;
       
   
}
   
   
Character( GameObject * object, float x, float y )
        :
Unit( object, x, y )
   
{
       
       
type = gameObjectType::Character;
       
       
helmet = dynamic_cast < Character * >( object )->helmet;
       
armor = dynamic_cast < Character * >( object )->armor;
       
pants = dynamic_cast < Character * >( object )->pants;
       
leftHand = dynamic_cast < Character * >( object )->leftHand;
       
rightHand = dynamic_cast < Character * >( object )->rightHand;
       
       
loadBody();
       
loadHelmet();
       
loadArmor();
       
loadPants();
       
loadLeftHand();
       
loadRightHand();
       
       
dialogue = dynamic_cast < Character * >( object )->dialogue;
       
       
talkWithTexture = getTexture( "GUI/talk" );
       
talkWithSprite = sf::Sprite();
       
talkWithSprite.setTexture( * talkWithTexture->texture );
       
talkWithSprite.setOrigin( talkWithTexture->cx, talkWithTexture->cy );
       
showHand = false;
   
}
   
   
~Character() {
       
    }
}
;
P-181690
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-12 04:31:38
Rozwiązanie jest proste. Wystarczyło zmienić destruktor na virtualny. Teraz musze wszystkie pozostałe klasy naprawić
C/C++
virtual ~Character() {
   
}
P-181691
tBane
Temat założony przez niniejszego użytkownika
» 2024-10-12 06:48:32
P-181693
pekfos
» 2024-10-13 11:37:58
Rozwiązanie jest proste. Wystarczyło zmienić destruktor na virtualny.
Konkretnie to chcesz mieć wirtualny destruktor w klasie, która będzie typem wskaźnika na którym chcesz wykonywać delete, lub w klasie bazowej tej klasy. Najlepiej niech to będzie klasa bazowa na szczycie hierarchii, wtedy możesz użyć dowolnego poprawnego typu wskaźnika.
P-181696
1 « 2 »
Poprzednia strona Strona 2 z 2