2017-01-02 2 views

Antwort

10

Verwenden Sie ein ::std::vector.

#include <vector> 

void foo() 
{ 
    ::std::vector<double> x; 
    x.resize(5); 
    x[4] = 2.0; 
    x.resize(2); 
    // etc... 
} 

Die Anwendungsfälle, die Sie erwähnen, sind genau, warum ::std::vector gemacht wurde.

Nun, wenn Sie einen Vektor kleinere Größe ändern, tut es normalerweise nicht ausplanen Speicher. Dies ist für eine Reihe von Gründen, und diese Frage Stackoverflow auf shrink_to_fit beschreibt, warum: Is shrink_to_fit the proper way of reducing the capacity a `std::vector` to its size?

Aber, wenn Sie wirklich auf die Umsetzung andeuten wollen, dass die zusätzlichen Punkte freigegeben werden sollen, dies tun:

#include <vector> 

void foo() 
{ 
    ::std::vector<double> x; 
    x.resize(5); 
    x.shrink_to_fit(); // It didn't get smaller here, but I'm guessing you may 
    x[4] = 2.0;  // not know that when you resize the vector in your own code. 
    x.resize(2); 
    x.shrink_to_fit(); 
    // etc... 
} 

Der Vektor kann die Zuordnung immer noch nicht verkleinern. Das ist ein Problem, das Sie bei Ihrer Implementierung berücksichtigen sollten, wenn es wirklich ein Problem ist.

Wenn es ein Problem ist, und Sie müssen unbedingt die Zuordnung schrumpfen und nicht die Umsetzung festgelegt werden lassen können, dann können Sie dies tun:

#include <iterator> 
#include <algorithm> 
#include <utility> 
#include <vector> 

template <class T> 
void shrinkwrap_vector(::std::vector<T> &x) 
{ 
    using namespace ::std; 
    typedef vector<T> vec_t; 

    const auto old_cap = x.capacity(); 
    x.shrink_to_fit(); // Try shrink_to_fit first to see if it works. 
    if ((x.capacity() == old_cap) && (old_cap > x.size())) { 
     vec_t t; 
     t.reserve(x.size()); 
     move(x.begin(), x.end(), back_inserter(t)); 
     swap(x, t); 
    } 
} 

dann rufen Sie einfach

shrinkwrap_vector(x); 

im Code statt x.shrink_to_fit(). Das würde deinen Vektor einfach in einen brandneuen Vektor kopieren, der so nah an der Größe ist, wie deine Implementierung es dir erlauben würde.

Beachten Sie auch, dass wenn Sie etwas speichern, das einen nicht-trivialen Destruktor hat (double hat einen trivialen Destruktor), wird dieser Destruktor für jedes gelöschte Element aufgerufen, wenn Sie eine resize machen. Die ganze shrink_to_fit Sache dreht sich nur um Speicherzuteilung, nicht um Konstruktion oder Zerstörung.

Schließlich, wenn Sie wirklich, wirklich die C malloc und realloc Aufrufe verwenden möchten, können Sie möglicherweise eine benutzerdefinierte vector Klasse erstellen, die diese verwendet. Sie müssen jedoch besonders vorsichtig sein, es sei denn, Sie machen Ihre benutzerdefinierte Klasse für double spezifisch. Sie müssen den Konstruktor für alle Elemente aufrufen, die nach der Zuweisung des Arbeitsspeichers hinzugefügt werden, und den Destruktor für alle gelöschten Elemente, bevor der Speicher freigegeben wird.

diese Art von Klasse zu schreiben, ist komplex. Sie müssen den Erwartungen für Container-Klassen in C++ entsprechen, damit es reibungslos mit allem anderen zusammenarbeitet. Dies beinhaltet das Erstellen von Iterator-Klassen und Dingen dieser Art.

+3

auf einen niedrigeren Wert Ändern der Größe nicht den Speicher frei. Wenn es wichtig ist, den Speicher freizugeben, müssen Sie möglicherweise die Funktion vector :: shrink_to_fit() verwenden. – Jadh4v

+0

@ Jadh4v - Das ist eine interessante Design-Wahl, die sie anscheinend gemacht haben. Ich kann nicht sagen, wie ich der Designwahl zustimme, aber es scheint, dass Sie richtig sind. – Omnifarious

+0

Danke Leute. Das ist sehr hilfreich. –

Verwandte Themen