2016-02-12 5 views
6

Wenn Sie die insert Mitgliedsfunktion auf einem std::vector aufrufen, wird es reserve vor dem "Zurückschieben" der neuen Elemente? Ich meine, garantiert der Standard das oder nicht?Ist std :: vector :: insert reserve per Definition?

Mit anderen Worten soll ich tun es wie folgt aus:

std::vector<int> a{1,2,3,4,5}; 
std::vector<int> b{6,7,8,9,10}; 
a.insert(a.end(),b.begin(),b.end()); 

oder so:

std::vector<int> a{1,2,3,4,5}; 
std::vector<int> b{6,7,8,9,10}; 
a.reserve(a.size()+b.size()); 
a.insert(a.end(),b.begin(),b.end()); 

oder eine andere bessere Lösung?

+1

Dies kann Ihre Frage beantworten: http://stackoverflow.com/questions/2208293/what-ist-most-efficient-way-to-append-one-stdvector-to-the-end-of -another –

+0

Es hängt davon ab, ob die Iteratoren Eingabe-Iteratoren oder streng stärker sind. Für etwas Stärkeres kann man mit "Abstand" rechnen. Es ist QoI, aber jede vernünftige Implementierung sollte nicht mehr als einmal neu zugewiesen werden. –

+0

Sowohl die libstdC++ - als auch die libC++ - Implementierung reserviert Platz für die gesamte Sequenz auf einmal, wenn mindestens Iteratoren vorhanden sind. –

Antwort

12

Im Hinblick auf die Komplexität der Funktion [link]:

Linear von der Anzahl der Elemente eingefügt (Kopieren/Verschieben Bau) plus die Anzahl der Elemente nach der Position (bewegen).

Außerdem, wenn InputIterator im Bereich Einsatz (3) nicht mindestens eine vorderen Iterator Kategorie ist (dh nur ein Eingang Iterator) die neue Kapazität kann nicht im voraus bestimmt werden, und das Einsetzen entsteht in zusätzlicher logarithmischer Komplexität in der Größe (Neuzuweisungen).

Daher gibt es zwei Fälle:

  • Die neue Kapazität bestimmt werden kann, deshalb werden Sie nicht
  • Die neue Kapazität reservieren aufrufen müssen nicht ermittelt werden kann, damit ein Anruf zu reserve sollte nützlich sein.
+0

Danke. Es gibt etwas, das ich nicht bekommen konnte. Die beiden Fälle sind implementierungssicher. Also sollte ich in meine Compiler-Implementierung eintauchen. Oder sie sind Fälle, die ich abhängig von meinem Code voraussagen sollte –

+0

Sie sollten den Fall vorhersagen. dh wenn Sie wissen, dass Sie einen Eingabe-Iterator geben werden, nennen Sie besser 'reserve' vorher. – dkg

1

Vom documentation, es scheint, dass:

Neuzuteilung Ursachen, wenn die neue Größe() größer ist als die alte Kapazität().

Beachten Sie auch, dass in einem solchen Fall alle Iteratoren und Referenzen ungültig sind.

Es versteht sich daher von selbst, dass Umschichtungen verantwortlich sind der insert und, wenn man sich diese Vorgänge zu der Zeit aussehen, es ist wie eine konsistente Reserve-size-plus-eins Betrieb bei jedem Schritt vorgenommen wird.
Sie können argumentieren, dass ein reserve Aufruf an der Spitze der Einfügung alles in jenen Fällen beschleunigen würde, wenn mehr als eine Umverteilung stattfindet ... Nun, richtig, es könnte helfen, aber es hängt meistens von Ihrem tatsächlichen Problem ab.

+1

OP bittet um etwas anderes: Er möchte wissen, ob eine Vorreservierung vor dem Einfügen stattfindet. – dasblinkenlight

+0

Sie meinen, wenn es als Ganzes reserviert ist, die Anzahl der einzufügenden Objekte bekannt zu sein? Es ist in der Tat offensichtlich, dass die Einfügung irgendwie für Neuzuweisungen sorgt, daher kann man sie als * Reserve-Größe-Plus-Eins * Anfrage für jeden Schritt betrachten (OK, abgesehen von der Leistung, logisch gesprochen). – skypjack

+1

Es scheint mir, dass OP möchte wissen, ob mehrere Zuteilungen während "einfügen" passieren können, und auch wenn die (implizit) reservierte Größe die tatsächliche Größe deutlich überschreiten könnte. – dasblinkenlight

1

Wird std::vector::insert per Definition reserviert?

Ja, nein; hängt von der aktuellen Kapazität ab.

Vom Entwurf N4567, §23.3.6.5/1 ([vector.modifiers]):

Verursacht Neuzuteilung wenn die neue Größe größer als die alte Kapazität ist.

Wenn die zugeordnete Speicherkapazität im vector groß genug ist, um die neuen Elemente enthalten, sind keine zusätzlichen Mittel für die vector benötigt. Also nein, dann wird es keinen Speicher reservieren.

Wenn die Kapazität vector nicht groß genug ist, wird ein neuer Block zugewiesen, der aktuelle Inhalt wird verschoben/kopiert und die neuen Elemente werden eingefügt. Der genaue Zuweisungsalgorithmus ist nicht spezifiziert, würde aber typischerweise wie in der reserve()-Methode verwendet werden.

... oder ein anderer besserer Ansatz?

Wenn Sie sich über zu viele Zuweisungen betroffen sind, während Elemente in die vector Einfügen dann mit der Größe der Anzahl der erwarteten Elemente der reserve Aufruf der Methode hinzugefügt werden die Zuweisungen nicht minimiert.

Ruft die vectorreserve vor den/irgendwelchen Einfügungen? I.e. Ordnet es genügend Kapazität in einer einzigen Zuweisung zu?

Keine Garantien. Wie würde es den Abstand zwischen den Eingabe-Iteratoren wissen? Vorausgesetzt, dass das insert-Verfahren einen InputIterator (d. H. Single-Pass-Iterator) annehmen kann, hat es keinen Grund, die erwartete Größe zu berechnen. Könnte die Methode die Größe berechnen, wenn die Iteratoren etwas anderes (z. B. Zeiger oder RandomAccessIterator)? Ja könnte es. Wäre es? Hängt von der Implementierung und den Optimierungen ab.

+0

Was meinst du, es wird nicht garantiert in Ihrem letzten Absatz ? Es wird und es gäbe keine Zuweisungen –

+0

@AlexeyAndronov. Es könnte Reserve nennen, selbst wenn es gerade genug Platz hat, die Algorithmen sind nicht spezifiziert, also könnte es in der Theorie ein bisschen mehr als Puffer reservieren wollen. – Niall

+0

[link] (http://www.cplusplus.com/reference/vector/vector/insert/): _ "Dies führt zu einer automatischen Neuzuweisung des zugewiesenen Speicherplatzes, wenn - und nur wenn - die neue Vektorgröße die aktuelle übersteigt Vektorkapazität. "_ –

Verwandte Themen