std::vector ruft Destruktor mehrmals während push_back auf?

Lesezeit: 4 Minuten

Ich drücke die Objektklasse tipo auf einen Vektor, wenn ich den ersten drücke, wird der Konstruktor aufgerufen (wie es sollte) und der Destruktor wird sofort aufgerufen (was meiner Meinung nach nicht passieren sollte). Wenn ich dann das nächste Objekt pushe, wird der Konstruktor einmal und der Destruktor zweimal aufgerufen, dann beim dritten dreimal und so weiter.

Es scheint, dass der Destruktor jedes Mal öfter aufgerufen wird, wenn ich etwas auf den Vektor schiebe.

Das ist meine Klasse:

class Item
{
protected:
...
public:
    Item();
    Item(char * no, int hit, int ve, char * pathTilesheet, int an, int al, bool inv, bool vol, bool fan, int mh = NULL);
    ~Item();
};


Item::Item(char *no, int hi, int ve, char *pathTilesheet, int an, int al, bool inv, bool vol, bool fan, int mh){    
    // CARGAR SDL
    tileSheet = load_image(pathTilesheet);
    tileSheetEspejo = flip_surface(tileSheet, FLIP_HORIZONTAL);
}

Folgendes passiert:

std::vector<Item> vecItems;
vecItems.push_back(Item("life",4,0,"assets/imagenes/hp.png", 8, 8, false, false, false));
// HERE THE CONSTRUCTOR AND THE DESTRUCTOR ARE CALLED
vecItems.push_back(Item("lifeXL",8,0,"assets/imagenes/hp-xl.png", 16, 16, false, false, false));
// HERE THE CONSTRUCTOR IS CALLED ONCE AND THE DESTRUCTOR TWICE
vecItems.push_back(Item("blast 1",-4,14,"assets/imagenes/bola.png", 8, 8, false, true, false));
// HERE THE CONSTRUCTOR IS CALLED ONCE AND THE DESTRUCTOR MULTIPLE TIMES

Mache ich etwas falsch? Warum könnte das passieren?

  • Es liegt wahrscheinlich an Kopien und Umverteilungen. Vector verwendet kontinuierlichen Speicher. Wenn Sie also seine Kapazität überschreiten, muss es einen größeren Teil des Speichers zuweisen, alle vorhandenen Elemente kopieren und dann den vorherigen Speicher freigeben.

    – Benutzer2802841

    10. November 2013 um 15:35 Uhr

  • Diese Frage könnte Sie interessieren: stackoverflow.com/q/13395984/1741542

    – Olaf Dietsche

    10. November 2013 um 15:36 Uhr

  • Um zu sehen, ob @user2802841 richtig ist, könnten Sie versuchen, vecItems.reserve(3) einzufügen; vor deinen Aussagen.

    – bennofs

    10. November 2013 um 15:36 Uhr

  • Zählen Sie die Aufrufe des Kopierkonstruktors, um zu sehen, ob das Gleichgewicht stimmt …

    – Stefan Haustein

    10. November 2013 um 15:37 Uhr

  • Wenn Sie einen Destruktor schreiben, müssen Sie sich wahrscheinlich um Kopieren und Zuweisung kümmern. Google “Dreierregel c++”.

    – Yakk – Adam Nevraumont

    10. November 2013 um 15:41 Uhr

Benutzer-Avatar
Mike Seymour

Jede Zeile Ihres Codes erstellt eine temporäre Item, kopiert es in den Speicher des Vektors und zerstört dann das Temporäre. Deshalb sehen Sie jedes Mal (mindestens) einen Destruktoraufruf.

In C++11 können Sie das Erstellen und Zerstören der temporären Datei vermeiden, indem Sie verwenden emplace_back(args...) eher, als push_back(Item(args...))um das Objekt direkt im Speicher des Vektors zu erstellen.

Außerdem muss der Vektor manchmal wachsen und einen größeren Speicherblock neu zuweisen, um alle seine Elemente in einem zusammenhängenden Array zu halten. Dabei wird jedes Element in den neuen Speicher verschoben und die alten Elemente werden zerstört. Aus diesem Grund sehen Sie manchmal mehr als einen Destruktoraufruf.

Sie können die Notwendigkeit einer Neuzuweisung vermeiden, wenn Sie die endgültige Größe des Vektors kennen, indem Sie anrufen reserve() um genügend Speicher zuzuweisen, bevor Sie beginnen. Alternativ gibt es Container wie deque und list die ihre Elemente nicht bewegen, wenn sie wachsen, die aber für andere Operationen weniger effizient sein können.

Abgesehen davon, wie in den Kommentaren erwähnt, müssen Sie, wenn die Klasse Ressourcen verwaltet (was durch das Vorhandensein eines Destruktors impliziert wird), wahrscheinlich den Kopierkonstruktor und den Kopierzuweisungsoperator gemäß der Dreisatzregel und bereitstellen oder löschen Vielleicht denken Sie darüber nach, es aus Effizienzgründen beweglich zu machen.

  • @Yakk: Das ist für die Frage nicht direkt relevant; aber ja, wenn die Klasse einen Destruktor benötigt, muss wahrscheinlich ihre Kopiensemantik repariert oder deaktiviert werden.

    – Mike Seymour

    10. November 2013 um 15:42 Uhr

  • Seine Frage ist, warum der Destruktor häufiger aufgerufen wird als der Konstruktor. Das liegt daran, dass er die Implementierung des Kopierkonstruktors und des Zuweisungsoperators verpasst hat. Wie Sie sehen können, weist das OP Ressourcen im ctor zu, die wahrscheinlich im dtor bereinigt werden, was zu Problemen führt, wenn der dtor dreimal für einen ctor aufgerufen wird. Das OP hat die falsche Frage gestellt, und die richtige Antwort beinhaltet das Schreiben eines Copy Ctor.

    – Yakk – Adam Nevraumont

    10. November 2013 um 16:17 Uhr

  • @Yakk: Die Frage fragt, warum der Destruktor mehrmals aufgerufen wird, und meine Antwort erklärt warum. Ich habe einen Hinweis hinzugefügt, warum dies ein Problem ist, wenn die Klasse eine ungültige Kopiersemantik hat, obwohl dies nur am Rande relevant ist.

    – Mike Seymour

    10. November 2013 um 16:26 Uhr

1012650cookie-checkstd::vector ruft Destruktor mehrmals während push_back auf?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy