Was passiert unter der Haube von vector::push_back Speicher her?
Meine Frage ist in Bezug auf die Wirkung von vector::push_back
, ich weiß, es fügt ein element am Ende des Vektors, aber was passiert unter der Haube?
IIRC Speicher-Objekte erfolgt in einer sequentiellen Weise, so meine Frage ist, ob vector::push_back
einfach mehr Speicher reserviert unmittelbar nach dem Vektor, und wenn ja, was passiert, wenn es ist nicht genügend freier Speicher in die Lage? Oder vielleicht einen Hinweis Hinzugefügt, das "Ende" zu verursachen, die vector zu "hüpfen", um den Ort geht es weiter? Oder ist es einfach nur umgeschichtet und durch kopieren an einen anderen Ort, der genug Platz hat und die alte Version wird verworfen? Oder vielleicht etwas anderes?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn genügend Platz ist bereits reserviert, das Objekt zu kopieren, wurden aus dem argument im Ort. Wenn es nicht genug Speicher, der Vektor wird wachsen interne databuffer folgenden einige Art von geometrischer progression (jedes mal, wenn die neue Größe wird
k*old_size
mitk > 1
[1]) und alle Objekte, die in der ursprünglichen Puffer werden dann verschoben auf die neuen Puffer. Nach Abschluss des Vorgangs den alten Puffer freigegeben wird, um das system.Im vorherigen Satz bewegen nicht in den technischen move-Konstruktor/move-Zuweisung Gefühl haben, Sie könnten verschoben oder kopiert oder durch eine entsprechende operation.
[1] Wächst um einen Faktor
k > 1
sorgt dafür, dass die fortgeführten Anschaffungskosten vonpush_back
konstant ist. Die eigentliche Konstante ist, variiert von einer Implementierung zu einer anderen (Dinkumware verwendet 1.5, gcc verwendet 2). Die fortgeführten Anschaffungskosten bedeutet, dass selbst wenn jeder so oft einepush_back
wird sehr teuer (O(N)
auf die Größe des Vektors zu der Zeit), diese Fälle sind selten genug, dass sich die Kosten für alle Operationen über das ganze set von Insertionen ist linear in der Anzahl der Einträge, und damit jede Einfügung Durchschnitte eine Konstante Kosten)int & x = myintvector[42]
und dann gehen Sie zum hinzufügen einer Menge von Elementen zum vector, genug zum auslösen bewegen. Darf ich genommen haben, dass der Verweis in den ersten Platz?push_back
errichtet ist im Ort, sondern vielmehr, dass das Objekt in der container ist gebaut in der Ort. Ob diese Kopie können Sie erstellte durch den compiler, ich bezweifle es, die parameter konstruiert, indem der Anrufer an den Ort des Anrufs, und es kann möglicherweise nicht wissen, die Lage wo sich das Objekt werden, muss der Anrufer zuordnen-und konstruieren das argument, dann übergeben Sie einen Verweis, um es zupush_back
alle, dass bevor zu wissen, die Lage der Puffer. (Ich gehe davon aus, dass keine tatsächlichen inlining, mit echten inlining kann alles passieren)myVector.push_back(MyObject())
. Dass jemand nicht weiß, wie viel C++ "liebt" der copy-Konstruktor könnte gedacht haben, dass das Objekt gebaut wurde, direkt im Ort.Beim vector ist der Speicherplatz zu verwenden, wird es die Zuweisung zu reserve mehr Platz.
Ist es an der Zuweisung zu entscheiden, wie dies umgesetzt wird.
Jedoch der Vektor, der entscheidet, wie viel Speicherplatz zu reservieren: der standard garantiert, dass die Vektor-Kapazitäten sollen wachsen, um mindestens einen Faktor 1,51 geometrisch (siehe Kommentar), damit verhindern, dass schreckliche Leistung durch wiederholte "kleine" Mittel.
Auf dem physischen verschieben/kopieren von Elementen:
1 ich habe versucht, zu finden die Referenz zitieren, für die von der n3242 standard-Entwurf, aber ich war nicht in der Lage zu finden, es zu diesem Zeitpunkt
Einen Vektor ergibt, dass alle Elemente contigious in Erinnerung.
Intern Sie können denken, es als definiert als drei Zeiger (oder was auch wirken wie Zeiger):
Wenn Sie drücken Sie zurück.
X*(capacity - start)*sizeof(t)
bytes.Wenn
vector
läuft out of space, es ist reserviert, und alle Elemente, die übernommen werden in das neue array. Das alte array wird dann zerstört.Zur Vermeidung eines übermäßigen Anzahl der Zuordnungen zu gewährleisten und die Durchschnittliche
push_back()
Zeit anO(1)
eine Umverteilung erfordert, dass die Größe erhöht werden, die durch mindestens einen Konstanten Faktor. (1.5 und 2 gemeinsam)realloc()
. Ich bin mir nicht sicher über den status dieser entweder.realloc
-ähnlichen Betrieb in derAllocator
Schnittstelle, verwendet von standard-Containern.vector
zuordnen muss ein neues array kopieren Sie den Inhalt, dann frei die alte. Vereinbart, dies ist ineffizient, da die Zuweisung vielleicht in der Lage gewesen zu erweitern, die vorhandene Zuweisung in-place, aber es hat nicht die chance bekommen. Ich würde genau hinsehen, um den standard zu beurteilen, wo eine Umsetzung zulässig ist, im Fall der Vektor mit den default-Zuweisung, die Einführung einer realloc-Stil-Optimierung gibt.operator new
zu erhalten, den Speicher, was bedeutet, dass ein Benutzer definiertoperator new
sehen kann, aber explizit sagt, dass "es ist nicht spezifiziert, Wann oder wie oft diese Funktion [operator new
] genannt wird." Das klingt nach genügend Spielraum, um eine solche Optimierung.vector
. Nichts darüber, wie viele Male (wenn überhaupt) der copy-Konstruktor aufgerufen wird.vector
sein könnte spezialisiert, indem die Umsetzung. Die Spezialisierung gilt für Vektoren, die Nutzungstd::allocator
. Da die Nutzer können sich spezialisierenstd::allocator
für user-defined types, würde es natürlich vermeiden, Vektoren, verwenden Spezialisierungen derstd::allocator
, so dass auch meine Besorgnis über die copy-Konstruktoren gelöst werden könnten, die auf dieses Konto zu. Zum Beispiel, wenn die Implementierungen nur spezialisiertstd::vector<T, std::allocator<T> >
für built-in TypenT
dann bist du sicher.vector
Verhalten im Allgemeinen, und wenn es bestimmte Implementierungen zu verwalten, dass eine Optimierung, die die neue Reihe in der Tat ist in der gleichen Lage wie das alte array, das ist schön, aber nicht verlassen.Beim Aufruf
vector::push_back
die Ende Zeiger ist im Vergleich zu den Kapazität Zeiger. Wenn dort ist genug Platz für das neue Objektplacement new
wird aufgerufen, um zu konstruieren, das Objekt in den verfügbaren Platz und die Ende Zeiger wird inkrementiert.Wenn es nicht genug Zimmer-das
vector
ruft seine Zuweisung genügend zusammenhängender Speicherplatz für wenigstens die vorhandenen Elemente plus new element (unterschiedliche Umsetzung wachsen kann den Speicher durch verschiedene Multiplikatoren). Dann werden alle vorhandenen Elemente plus die neue kopiert, den neu zugewiesenen Platz.std::vector overallocates - es wird in der Regel die Zuweisung von mehr Speicher als notwendig, automatisch.
size
ist nicht affectd, aber Sie können Steuern, die durchcapacity
.std::vector kopieren alles, wenn die zusätzliche Kapazität ist nicht ausreichend.
Den Speicher std::vector ist roh, keine Konstruktoren aufgerufen werden, auf Nachfrage, mit dem placement-new.
So, push_back macht:
Wenn Sie eine Idee haben von dem, was die endgültige Größe der Arrays, versuchen
vector::reserve
den Speicher zuerst. Beachten Sie, dassreserve
unterscheidet sich vonvector::resize
. Mitreserve
dievector::size()
Ihrer array wird nicht geändert