Ist es besser, vector :: reserve () vor dem Aufruf von vector :: assign () aufzurufen?

8

Ich verstehe, dass es eine gute Übung ist, "Reserve" zu verwenden, um unnötige Neuzuweisungen zu vermeiden (Punkt 14 von Effective STL):

%Vor%

Gilt die gleiche Regel, wenn Sie assign aufrufen?

%Vor%     
jpen 01.07.2012, 14:49
quelle

2 Antworten

6

Wenn v1 % std::vector ist, brauchst du es nicht wirklich, da der Compiler / stl weiß wie viele Elemente in v2 stehen (und reserve die benötigte Menge selbst vorher) Kopieren der tatsächlichen Daten).

Für den generischen Fall kann es jedoch sinnvoll sein, reserve im Voraus den benötigten Betrag einzugeben, wenn der Eingabebehälter ( v1 ) nicht weiß, wie viele Artikel vorhanden sind und Sie die Nummer zur Hand haben .

    
Vlad 01.07.2012, 14:53
quelle
6

Ob reserve aufgerufen werden soll oder nicht, hängt von:

ab
  • der Iteratortyp: Bei Eingabe-Iteratoren kann die Implementierung die Größe
  • nicht erraten
  • die Qualität der Bibliothek: sie kann sich nicht auf "bessere" Iteratoren spezialisieren
  • ob Leistung die Verringerung der Wartbarkeit wert ist

Nehmen wir die 3 Punkte in der richtigen Reihenfolge.

1) Iterator-Typ

Die Methode assign benötigt zwei Iteratoren, die mindestens dem InputIterator -Modell entsprechen müssen. Das Problem ist, dass dieses Modell reine Quellen darstellt (wie die Bytes, die aus dem Netzwerk kommen): Sie können etwas zweimal daraus konsumieren. Als Ergebnis ist es bei zwei InputIterator nicht möglich, den Abstand zwischen ihnen zu berechnen, ohne die Daten zu extrahieren (es sei denn, Sie wollen die Daten überhaupt nicht, aber darum geht es nicht), so dass Sie nicht "reservieren" können "Zuerst.

Dies wird durch die Tatsache veranschaulicht, dass std::distance mindestens FowardIterator erfordert.

2) Die Qualität der Implementierung

Ich glaube nicht, dass der Standard tatsächlich "bessere" Iteratoren vorschreibt (die zumindest ForwardIterator modellieren), dass die Implementierung von assign den Bereich zweimal durchläuft. In einer Berechnung, die durch die Speicherbandbreite begrenzt ist (man stelle sich vor, diese Information auf einem Band mit einer sehr langsamen Rückspulzeit zu lesen), wäre dies tatsächlich kostspieliger.

Viele Implementierungen (wie zB libc ++, siehe unten) spezialisieren sich jedoch auf assign , so dass sie bei ForwardIterator zuerst std::distance aufruft, um die richtige Menge an Speicher zu reservieren, falls nötig.

Hinweis: Das gleiche gilt übrigens für Masseneinfügungen.

3) Wartungsaufwand

Ich würde bemerken, dass Sie trotz des möglichen Gewinns (vielleicht unwissentlich) hier Informationen duplizieren.

%Vor%

Sehen Sie, wie das Aussehen der neuen Zeile den Code plötzlich falsch macht? Nicht, dass es nicht funktioniert, aber die angebliche Optimierung ist nicht mehr so ​​richtig: Sie reservieren jetzt zu viel!

Persönlich würde ich meiner Implementierung der Standardbibliothek vertrauen, um das Richtige zu tun. Die Leute, die sie schreiben, haben viel mehr Erfahrung als ich.

Und wenn es sich wirklich um einen identifizierten Engpass in Ihrer Anwendung handelt, können Sie es immer versuchen. Schreiben Sie einfach eine reserve_and_assign -Methode, um deutlich zu machen, was sie tut, und messen Sie, ob es besser ist.

Als Referenz finden Sie hier die libc ++ - Implementierung hier :

%Vor%     
Matthieu M. 01.07.2012 16:05
quelle

Tags und Links