Die erste Lösung ist:
std::vector<int> *vec = new std::vector<int>;
assert(vec != NULL);
// ...
delete vec;
Eine Alternative ist:
std::vector<int> v;
//...
vec.clear();
vec.swap(std::vector<int>(vec));
Die zweite Lösung ist ein bisschen ein Trick - was ist der "richtige" Weg, um es zu tun?
Ich bin mir bewusst, dass der Destruktor aufgerufen wird, sobald er vom Stapel ist. Ich war neugierig auf andere Methoden.
Die einfachste und zuverlässigste Methode, einen Vektor freizugeben, besteht darin, ihn auf dem Stack zu deklarieren und einfach nichts zu tun.
void Foo() {
std::vector<int> v;
...
}
C++ garantiert, dass der Destruktor von v
aufgerufen wird, wenn die Methode ausgeführt wird. Der Destruktor von std::vector
sorgt dafür, dass der zugewiesene Speicher freigegeben wird. Solange der T
-Typ von vector<T>
über eine korrekte C++ - Deallocation-Semantik verfügt, ist alles in Ordnung.
Der einfachste Weg, den gesamten Speicher in einem Vektor freizugeben, ohne das Vektorobjekt selbst zu zerstören, ist
vec = std::vector<int>();
Ihre zweite Variante hat den gleichen Effekt, sie springt jedoch durch weitere Reifen. Der Trick "Kopieren und Austauschen" hebt die zusätzliche Kapazität im Vektor auf und kann nützlich sein, wenn er einige Daten enthält, die Sie behalten möchten. Wenn keine Daten vorhanden sind, müssen Sie weder kopieren noch austauschen.
std::vector<int> vi;
/*Push lots of stuff into the vector*/
// clean it up in C++03
// no need to clear() first
std::vector<int>().swap(vi);
// clean it up in C++0x
// not a one liner, but much more idiomatic
vi.clear();
vi.shrink_to_fit();
Ich stimme mit Mike Seymour überein. Probieren Sie dies aus, dann werden Sie feststellen, dass das letzte funktioniert
const int big_size = 10000;
vector<double> v( big_size );
cout << "Before clearing, the capacity of the vector is "
<< v.capacity() << " and its size is " << v.size();
v.clear();
cout << "\nAfter clearing, the capacity of the vector is "
<< v.capacity() << " and its size is " << v.size();
vector<double>().swap( v );
cout << "\nAfter swapping, the capacity of the vector is "
<< v.capacity() << " and its size is " << v.size();
vector<double> v1( big_size );
v1 = vector<double>();
cout << "\n After vector<double>();, the capacity of the vector is "
<< v1.capacity() << " and its size is " << v1.size();
Verwenden Sie keine Speicherzuordnungsfunktionen, es sei denn, Sie müssen dies wirklich tun. Wenn Ihre Klasse immer einen Vektor benötigt, fügen Sie einfach das Element std :: vector direkt hinzu. Hier müssen Sie keine Speicherzuordnung vornehmen.
In den Fällen, in denen Sie den dynamischen Vektor benötigen, ist das Zuordnen und Löschen wie in Ihrem ersten Beispiel 100% korrekt.
Im zweiten Beispiel wird der Aufruf von std :: swap strikt nicht benötigt, da die clear-Methode den Vektor löscht und ihn leer macht. Ein mögliches Problem besteht darin, dass es keine Garantie gibt, dass der Vektor den Speicher tatsächlich freigibt und an das Betriebssystem (oder die Laufzeit) zurückgibt. Der Vektor behält möglicherweise den zugewiesenen Speicher für den Fall, dass Sie den Vektor unmittelbar nach dem Löschen füllen. Der Aufruf von std :: swap kann ein Trick sein, um den Vektor zu zwingen, seine internen Daten freizugeben. Es kann jedoch nicht garantiert werden, dass dies tatsächlich geschieht.
Ich vermute hier, dass Sie einen Vektor haben, der vorübergehend eine große Datenmenge enthält. Nachdem der Vektor gelöscht wurde, nimmt er immer noch den gesamten Speicher auf. Sie möchten diesen Speicher freigeben, nachdem Sie damit fertig sind, aber die Funktion/das Objekt, mit dem Sie arbeiten, ist noch nicht abgeschlossen.
Lösungen in abnehmender Reihenfolge der Erwünschtheit:
Der einzige technische Unterschied zwischen Tauschen und Löschen besteht darin, dass der Basisvektor selbst nicht zerstört wird. Dies ist ein kleiner Aufwand und es lohnt sich nicht, sich darüber Sorgen zu machen (solange Sie den Vektor letztendlich zerstören)
Die größere Überlegung ist, dass es einfacher ist, korrekten Code zu schreiben, und ich glaube, Swap gewinnt beim Löschen an Stelle, ist aber schlimmer, als den Vektor an einen anderen Ort zu verschieben.
Wenn Sie den Vektor nur aus dem Geltungsbereich herausnehmen lassen, wird er sich ohne zusätzliche Arbeit entsprechend aufräumen. Wenn der Vektor eine Membervariable einer Klasse ist und der Inhalt freigegeben werden soll, bevor der Besitzer des Objekts zerstört wird, rufen Sie einfach vec.clear () auf.
Wenn Sie den Vektor beibehalten, den Speicher jedoch freigeben möchten, der den Inhalt enthält, wird vec.swap(std::vector<int>());
dies tun. Es ist nicht erforderlich, das temporäre Element in das Original zu kopieren, es sei denn, vec enthält Elemente, die Sie behalten möchten, und Sie möchten nur den zugewiesenen Speicher auf eine Größe reduzieren, die der aktuellen Größe () entspricht.
Falls der Vektor wirklich auf dem Heap sein muss, vergessen Sie nicht:
std::auto_ptr<std::vector<int> > vec(new std::vector<int>);
besonders nützlich bei Code wie:
std::auto_ptr<std::vector<int> > vec(vectorFactoryFunction());
Dies ist kein gültiger Vergleich, da sich die Beispiele auf verschiedene Arten von Objekten beziehen: dynamische Dauer und lokale Dauer. Sie können den Destruktor OR mit dem Swap-Trick (aka shrink_to_fit) mit einem der beiden aufrufen. Die Art von right hängt davon ab, ob Sie das Vektorobjekt benötigen oder nicht.
Es kann beispielsweise erforderlich sein, dass sie persistent ist wenn es Verweise oder Hinweise darauf gibt die gültig bleiben müssen. In diesem Fall ist das Verkleinern der einzige Weg, unabhängig von der Zuweisung.
Ich bin nicht sicher, warum Ihr zweites Beispiel einen Kopierkonstruktor für den temporären statt einen Standardkonstruktor verwendet. Das würde Ihnen die .clear()
Codezeile ersparen.
Sie können dieses generisch für jedes Objekt festlegen, auch wenn es sich nicht um einen Container handelt. Ich gehe davon aus, dass sich std :: swap darauf spezialisiert hat, vector :: swap aufzurufen.
template<typename T>
void ResetToDefault(T & value)
{
std::swap(T(), value);
}
std::vector<int> vec;
//...
ResetToDefault(vec);
Löschen hebt den Speicher auf, der Speicher ist dann für das nächste Objekt frei, aber der Vektor ist verschwunden.
Der zweite Trick gibt überschüssigen Speicher frei, lässt den Vektor jedoch intakt, aber leer.
Obwohl beide zu funktionieren scheinen, sehe ich keinen Grund, nicht einfach delete auf dem Zeiger aufzurufen. Der Vektor sollte einen Destruktor haben, der alles andere behandelt.