Wie setze ich die Anfangsgröße von std :: vector?

130

Ich habe eine vector<CustomClass*>und ich habe viele Elemente in den Vektor eingefügt und ich benötige einen schnellen Zugriff, daher verwende ich keine Liste. Wie stelle ich die Anfangsgröße des Vektors ein (z. B. 20.000 Stellen, um das Kopieren beim Einfügen eines neuen zu vermeiden)?

Damir
quelle
1
Es gibt einen Konstruktor und zwei Funktionen dafür in jeder std::vectorReferenz, je nachdem, welche Ihren Anforderungen besser entspricht.
Chris
1
Sie können das Kopieren nicht vermeiden, indem Sie nur den Anfangswert festlegen.
Juanchopanza
1
Kopien von vermeiden? Das Speichern von Zeigern ist in Bezug auf die Kopierkosten recht einfach.
user7116
1
@ Damir, meintest du std::vectorim Titel?
Robᵩ

Antworten:

180
std::vector<CustomClass *> whatever(20000);

oder:

std::vector<CustomClass *> whatever;
whatever.reserve(20000);

Ersteres legt die tatsächliche Größe des Arrays fest, dh es wird zu einem Vektor von 20000 Zeigern. Letzteres lässt den Vektor leer, reserviert jedoch Platz für 20000 Zeiger, sodass Sie (bis zu) so viele einfügen können, ohne dass er neu zugewiesen werden muss.

Zumindest meiner Erfahrung nach ist es ziemlich ungewöhnlich, dass beide einen großen Unterschied in der Leistung bewirken - aber beide können unter bestimmten Umständen die Korrektheit beeinträchtigen. Insbesondere solange keine Neuzuweisung stattfindet, bleiben Iteratoren in den Vektor garantiert gültig, und sobald Sie die Größe / den reservierten Speicherplatz festgelegt haben, werden Sie garantiert keine Neuzuweisungen mehr erhalten, solange Sie dies nicht tun. t Vergrößern Sie darüber hinaus.

Jerry Sarg
quelle
Welche davon wäre für eine große Anzahl von Einfügungen / Löschungen effizienter?
Ctor
3
@Loggie: Ich bezweifle, dass es einen Unterschied in der Effizienz geben würde. Meistens ändert sich die Art und Weise, wie Sie es verwenden. Bei ersteren adressieren Sie nur die Zeiger, also so etwas wie whatever[10000] = somepointer;, bei letzteren müssen Sie zu push_backjedem Zeiger, den Sie hinzufügen. Zumindest wenn Sie daran gewöhnt sind, vectorist letzteres wahrscheinlich einfacher und natürlicher.
Jerry Coffin
Wenn die Größe des Containers bekannt ist, aus dem kopiert wird, warum ist es dann nicht effizienter, die Größe (neu) zu bestimmen und dann zu kopieren, anstatt sie zurückzuschieben?
1
@Cincinnatus: Weil es einen Aufruf von hat reserve, der die Speichergröße vorab zuweist . Theoretisch könnte das Einstellen der Größe immer noch geringfügig schneller sein, da auch vermieden wird, dass die aktuelle Größe jedes Mal erhöht wird, wenn Sie ein Element hinzufügen. In Wirklichkeit bezweifle ich, dass Sie das messen können.
Jerry Coffin
1
Wenn Sie dies auf einem heißen Pfad tun und der Code häufig aufgerufen wird, können Sie viel Anweisungen geben und Zeit sparen.
Bayindirh
15

Sie müssen die Reservefunktion verwenden, um eine anfänglich zugewiesene Größe festzulegen, oder dies im anfänglichen Konstruktor tun.

vector<CustomClass *> content(20000);

oder

vector<CustomClass *> content;
...
content.reserve(20000);

Wenn Sie reserve()Elemente verwenden, vectorwird genügend Speicherplatz für (mindestens?) So viele Elemente zugewiesen. Die Elemente sind in der nicht vorhanden vector, aber der Speicher kann verwendet werden. Dies wird dann möglicherweise beschleunigt, push_back()da der Speicher bereits zugewiesen ist.


quelle
Die Zuweisung der Größe kann auch während der Konstruktion erfolgen, indem ein integrales Argument (z. B. std::vector<Custom Class*> content(100);) übergeben wird
adelbertc
@kstruct: Ja, aber es kann weniger effizient sein - um einen sehr kleinen Betrag.