webentwicklung-frage-antwort-db.com.de

C++ - Löschvektor, Objekte, freier Speicher

Ich bin total verwirrt in Bezug auf das Löschen von Dingen in C++ Wenn ich ein Array von Objekten deklariere und die Funktion clear() verwende. Kann ich sicher sein, dass der Speicher freigegeben wurde?

Zum Beispiel : 

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

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

Kann ich sicher telefonieren, um den gesamten Speicher freizugeben? Oder muss ich das Löschen nacheinander wiederholen?

tempVector.clear();

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

vector<tempObject> *tempVector;
//Push objects....
tempVector->clear();
39
mister

Sie können clear aufrufen, und das wird alle Objekte zerstören, aber den Speicher nicht freigeben. Das Durchlaufen der einzelnen Elemente wird auch nicht helfen (welche Aktion würden Sie vorschlagen, um die Objekte auszuführen?) Was Sie tun können, ist dies:

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

Dadurch wird ein leerer Vektor ohne zugewiesenen Speicher erstellt und mit tempVector ausgetauscht, wodurch der Speicher effektiv freigegeben wird.

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

74

Hier gibt es zwei verschiedene Dinge:

  1. objektlebensdauer
  2. lagerdauer

Zum Beispiel:

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

Bei 1 löschen Sie v: Dies zerstört alle Objekte, die es gespeichert hat. Jeder erhält seinen Destruktor, falls er einen geschrieben hat, und alles, was sich im Besitz von MyObject befindet, ist jetzt freigegebenWie auch immer, vector v hat das Recht, den Rohspeicher für später zu behalten.

Wenn Sie sich zwischen 1 und 2 noch ein paar Dinge hineinschieben, spart dies Zeit, da der alte Speicher wiederverwendet werden kann.

Bei 2 ist der Vektor v außerhalb des Gültigkeitsbereichs: Alle Objekte, die Sie seit 1 hineingeschoben haben, werden zerstört (als ob Sie explizit wieder clear aufgerufen hätten), aber jetzt wird auch der darunterliegende Speicher freigegeben (v) wiederverwenden Sie es mehr).


Wenn ich das Beispiel so ändere, dass v ein Zeiger wird, müssen Sie ihn explizit löschen, da der Zeiger, der den Gültigkeitsbereich von 2 verlässt, dies nicht für Sie tut. In diesem Fall ist es besser, etwas wie std::unique_ptr zu verwenden. Wenn dies nicht der Fall ist und v durchgesickert ist, wird auch der zugewiesene Speicher durchgesickert. Wie oben müssen Sie sicherstellen, dass v gelöscht wird und der Aufruf von clear nicht ausreicht.

20
Useless

vector::clear() gibt keinen Speicher frei, der vom Vektor zum Speichern von Objekten zugewiesen wurde. Es ruft Destruktoren für die Objekte auf, die es enthält. 

Wenn der Vektor beispielsweise ein Array als Hintergrundspeicher verwendet und derzeit 10 Elemente enthält, ruft der Aufruf von clear() den Destruktor jedes Objekts im Array auf,, aber das Backing-Array wird nicht freigegeben sizeof(T) * 10 Bytes, die dem Vektor zugewiesen sind (mindestens). size() ist 0, aber size() gibt die Anzahl der Elemente im Vektor zurück, nicht notwendigerweise die Größe des Hintergrundspeichers.

Was Ihre zweite Frage betrifft, müssen Sie alles, was Sie mit new zuweisen, mit delete freigeben. Aus diesem Grund pflegen Sie normalerweise keinen Zeiger auf einen Vektor. Es gibt selten (wenn überhaupt) einen guten Grund dafür, und Sie verhindern, dass der Vektor bereinigt wird, wenn er den Bereich verlässt. Der Aufruf von clear() verhält sich jedoch unabhängig von der Zuweisung immer gleich.

14
Ed S.

Wenn Sie den Vektor immer und immer wieder verwenden müssen und Ihr aktueller Code ihn innerhalb Ihrer Schleife oder bei jedem Funktionsaufruf wiederholt deklariert, ist wahrscheinlich nicht genügend Arbeitsspeicher verfügbar. Ich schlage vor, dass Sie es außerhalb deklarieren, als Zeiger in Ihren Funktionen übergeben und verwenden:

my_arr.resize()

Auf diese Weise verwenden Sie immer die gleiche Speichersequenz für Ihre Vektoren, anstatt jedes Mal neue Sequenzen anzufordern. Hoffen Sie, dass dies geholfen hat. Beachten Sie: Wenn Sie die Größe des Vektors auf verschiedene Größen ändern, können sich Zufallszahlen ergeben. Übergeben Sie eine ganze Zahl wie 0, um sie bei Bedarf zu initialisieren.

0
user3715882

wenn ich die clear() Mitgliedsfunktion benutze. Kann ich sicher sein, dass der Speicher freigegeben wurde?

Nein, die Mitgliedsfunktion clear() zerstört jedes im Vektor enthaltene Objekt, lässt aber das Kapazität des Vektors unverändert. Dies wirkt sich auf die Größe des Vektors aus, jedoch nicht auf die Kapazität.

Wenn Sie die Kapazität eines Vektors ändern möchten, können Sie das Klartext und Minimiertext verwenden, d. H. Einen (temporären) leeren Vektor erstellen und dann beide Vektoren austauschen.


Sie können leicht sehen, wie sich jeder Ansatz auf die Kapazität auswirkt. Betrachten Sie die folgende Funktionsvorlage, die die Memberfunktion clear() für den übergebenen Vektor aufruft:

template<typename T>
auto clear(std::vector<T>& vec) {
   vec.clear();
   return vec.capacity();
}

Betrachten Sie nun die Funktionsvorlage empty_swap(), die den übergebenen Vektor durch einen leeren ersetzt:

template<typename T>
auto empty_swap(std::vector<T>& vec) {
   std::vector<T>().swap(vec);
   return vec.capacity();
}

Beide Funktionsschablonen geben die Kapazität des Vektors zum Zeitpunkt der Rückgabe zurück. Dann:

std::vector<double> v(1000), u(1000);
std::cout << clear(v) << '\n';
std::cout << empty_swap(u) << '\n';

ausgänge:

1000
0
0
El Profesor