2012-05-05 19 views
31

Ich bin total verwirrt in Bezug auf das Löschen von Dingen in C++ Wenn ich ein Array von Objekten deklarieren und wenn ich die clear() Funktion verwenden. Kann ich sicher sein, dass die Erinnerung freigegeben wurde?C++ löschen Vektor, Objekte, Freier Speicher

Zum Beispiel:

tempObject obj1; 
tempObject obj2; 
vector<tempObject> tempVector; 

tempVector.pushback(obj1); 
tempVector.pushback(obj2); 

Kann ich sicher klar rufen alle Speicher freizugeben? Oder muss ich iterieren, um eins nach dem anderen zu löschen?

tempVector.clear(); 

Wenn dieses Szenario in einen Zeiger von Objekten geändert wird, wird die Antwort die gleiche wie oben sein?

+1

Es gibt nichts anderes als den ersten Fall, außer dass es auf einen Vektor zeigt. Ich denke, diese Frage sollte erweitert werden, damit Sie verstehen, wie die Speicherzuteilung/-freigabe funktionieren sollte, und wahrscheinlich auch Hinweise. – Marlon

+0

Dieser sagt, dass die Deklaration in einem Funktionsstapel automatisch den Destruktor beim Schließen aufruft. https://stackoverflow.com/questions/3054567/right-way-to-deallocate-an-stdvector-object –

Antwort

62

Sie können löschen, und das wird alle Objekte zerstören, aber das wird den Speicher nicht freigeben. Looping durch die einzelnen Elemente wird nicht helfen, entweder (welche Maßnahmen würden Sie selbst vorschlagen auf die Objekte zu nehmen?) Was Sie tun können, ist dies:

vector<tempObject>().swap(tempVector); 

, dass ein leerer Vektor ohne Erinnerung schaffen wird zugewiesen und tauschen es mit tempVector, effektiv den Speicher freigeben.

C++ 11 hat auch die Funktion shrink_to_fit, die Sie nach dem Aufruf von clear() aufrufen könnten, und es würde theoretisch die Kapazität verkleinern, um die Größe anzupassen (die jetzt 0 ist). Dies ist jedoch eine unverbindliche Anfrage, und Ihre Implementierung kann sie ignorieren.

+0

Hey vielen Dank für die Antwort. Stört es Sie zu erklären, was das oben genannte tut? Nachdem ich das angerufen habe, muss ich dann anrufen? – mister

+3

@dupdupdup: Nein, Sie müssen nicht anrufen. Die Objekte in tempVector werden in den leeren Vektor übertragen. Dann wird der leere Vektor, da es ein namenloses temporäres Objekt ist, zerstört, und sein Inhalt, der zuvor tempVector gehörte, wird zerstört und die Speicherfreigabe aufgehoben. –

+0

Ich bin kein C++ - Experte, mein Verstand erklärt, wie das besser ist als die 'tempVector.resize (0)' würde ich zuerst versuchen? – delnan

14

vector::clear() nicht Speicher freigegeben durch den Vektor zum Speichern von Objekten; Es ruft Destruktoren für die Objekte auf, die es enthält.

Wenn beispielsweise der Vektor ein Array als Sicherungsspeicher verwendet und enthält derzeit 10 Elemente, dann clear() rief den destructor jeden Objekt in dem Array nennen, aber die Trägeranordnung nicht freigegeben werden, so dass es ist immer noch sizeof(T) * 10 Bytes, die dem Vektor (zumindest) zugeordnet sind. size() ist 0, aber size() gibt die Anzahl der Elemente im Vektor zurück, nicht unbedingt die Größe des Hintergrundspeichers.

Wie für Ihre zweite Frage, alles, was Sie mit new zuweisen, müssen Sie mit delete freigeben. Aus diesem Grund pflegen Sie normalerweise keinen Zeiger auf einen Vektor. Es gibt selten (wenn überhaupt) einen guten Grund, dies zu tun, und Sie verhindern, dass der Vektor aufgeräumt wird, wenn er den Bereich verlässt. Der Aufruf von clear() wird jedoch immer noch auf die gleiche Weise ausgeführt, unabhängig davon, wie es zugewiesen wurde.

18

Es gibt zwei verschiedene Dinge hier:

  1. Objekt Lebensdauer
  2. Speicherdauer

Zum Beispiel:

{ 
    vector<MyObject> v; 
    // do some stuff, push some objects onto v 
    v.clear(); // 1 
    // maybe do some more stuff 
} // 2 

Bei 1, Sie klar v: das alles zerstört die Objekte, die es gespeichert hat. Jeder bekommt seinen Destruktor aufgerufen, wenn du einen geschrieben hast und alles, was zu diesem MyObject gehört, ist jetzt freigegeben. Jedoch, Vektor v hat das Recht, den rohen Speicher herum zu behalten, wenn Sie es später wünschen.

Wenn Sie zwischen 1 und weitere Dinge hineinschieben, spart dies Zeit, da der alte Speicher wieder verwendet werden kann.

Bei 2, der Vektor v geht out of scope: alle Objekte, die Sie hineingeschoben, da 1 zerstört werden (als ob Sie ausdrücklich klar wieder genannt würden), aber jetzt ist der zugrunde liegende Speicher wird auch freigegeben (v won‘ t sein, um es wiederzuverwenden).


Wenn ich das Beispiel ändern, so v einen Zeiger wird, müssen Sie es explizit löschen, wie der Zeiger auf 2 out of scope gehen, dass nicht für Sie tun. Es ist besser, etwas wie std::unique_ptr in diesem Fall zu verwenden, aber wenn Sie nicht und v durchgesickert ist, wird der Speicher, den es zugeteilt hat, auch geleakt. Wie oben müssen Sie sicherstellen, dass v gelöscht ist, und der Aufruf clear ist nicht ausreichend.

+0

Was meinen Sie mit "Wenn Sie sich entscheiden, zu drücken .. das spart Zeit, da es den alten Speicher wiederverwenden kann."? Warum spielt altes Gedächtnis eine Rolle, wenn Sie neue Elemente hinzufügen möchten? – user13107

+0

Der Vektor muss den Speicher intern für die Objekte verwalten, die er speichert. Das Erstellen eines neuen Vektors erfordert das Zuweisen neuer Speicher, aber das Löschen und erneute Verwenden eines vorhandenen Vektors ermöglicht (aber garantiert nicht) die Wiederverwendung seines bereits zugewiesenen Speichers. – Useless

0

Wenn Sie den Vektor immer und immer wieder verwenden müssen und Ihr aktueller Code wiederholt in der Schleife oder bei jedem Funktionsaufruf deklariert wird, ist wahrscheinlich nicht genügend Speicher vorhanden. Ich schlage vor, dass Sie es außerhalb erklären, geben sie als Zeiger in Ihren Funktionen und Verwendung:

my_arr.resize() 

Auf diese Weise halten Sie die gleiche Speichersequenz für Ihre Vektoren stattdessen für neue Sequenzen jedes Mal anzufordern. Hoffe das half. Hinweis: Wenn Sie die Größe auf verschiedene Größen ändern, können zufällige Werte hinzugefügt werden. Übergeben Sie eine Ganzzahl wie z. B. 0, um sie bei Bedarf zu initialisieren.

Verwandte Themen