Ist es tatsächlich überall garantiert, dass der folgende Trick mit reduzierter Kapazität "funktioniert"?
%Vor%Es scheint für mich nicht zu funktionieren (insofern die Kapazität nicht Null ist), und ich kann im Standard nichts finden, was mehr sagt, als dass der "Inhalt" zwischen den beiden ausgetauscht werden muss zwei [hier, identische] Objekte.
Ähnliches gilt für Sequenzcontainer:
%Vor%Soweit ich weiß, ist dieser "Trick" weit verbreitet; vielleicht ist diese weit verbreitete Adoption fehlgeleitet?
(Natürlich, in C ++ 11 haben wir shrink_to_fit
[wenn auch nicht bindend] statt dessen, was diese Art von Unsinn macht.)
Ich habe schon immer gelernt, dass es keinen garantierten Standard gibt, um die Kapazität zu senken. Alle Methoden wurden (und sind noch) implementiert.
§ 23.2.1 \ 8 sagt:
Der Ausdruck
a.swap(b)
, für die Containera
undb
eines Standards Containertyp außerarray
, soll die Werte vona
undb
tauschen ohne irgendwelche Bewegungen, Kopien oder Tauschoperationen für die Person aufzurufen Containerelemente ...
Dies garantiert, dass die internen Zeiger der Vektoren getauscht werden müssen.
Ich kann jedoch nichts finden, was die Kapazität eines neu erzeugten Vektors garantiert.
§ 21.4.2 \ 1 besagt, dass eine der Nachbedingungen des basic_string
default-Konstruktors lautet, dass capacity()
einen nicht angegebenen Wert zurückgibt.
§ 21.4.2 \ 3 besagt, dass eine der Bedingungen des Copy-Konstruktors basic_string lautet, dass capacity()
einen Wert liefert, der mindestens so groß ist wie size()
.
§ 21.4.6.8 \ 2 besagt, dass string::swap
in konstanter Zeit läuft, was (effektiv) erfordert, dass die internen Zeiger getauscht werden.
Soweit ich das beurteilen kann, könnte eine konforme Implementierung string::max_size() { return 4;}
haben, und das Auslagern aller Interna von einem Puffer zu einem anderen wäre daher eine konstante Zeit. (Vektor kann das nicht tun)
Offensichtlich nehmen Sie das alles mit einem Körnchen Salz. Ich zitiere aus dem C ++ - Entwurf vom 28. Februar '11, und ich kann keine Spezifikationen für den Kopierkonstruktor des Vektors finden. Auch das Finden von Beweis für ist nicht dasselbe wie das Finden von Beweis gegen .
Auf seiner Errata-Seite für "Effective STL" bemerkt Scott Meyers:
Wenn Stringimplementierungen die Referenzzählung verwenden, der Tauschtrick Die Verwendung des Kopierkonstruktors verringert nicht die Kapazität, da der Der Kopierkonstruktor weist keinen Speicher zu; es passt nur ein Referenzzahl. Eine zuverlässigere Methode zum Ausführen von Shrink-to-Fit ist die temporäre Zeichenfolge über den Bereichserzeuger erstellen, z. Zeichenfolge (s.begin (), s.end ()). swap (s); Diese Version des Tauschtricks ist sicherer für Vektoren, weil es die Chance, dass die Kopie Konstruktor kopiert die Überkapazität des anderen Vektors (die Implementierungen dürfen tun).
Was die "Garantie" betrifft, bemerkt Meyers:
Die Sprachpolizei verlangt, dass ich Ihnen sage, dass es keine gibt garantieren, dass diese Technik Überkapazitäten wirklich beseitigt. Implementierer können Vektoren und Zeichenfolgen überschüssige Kapazität geben, wenn sie wollen und manchmal wollen sie. [Effektive STL, Punkt 17]
Von Ссылка :
Einige Implementierungen können die Kapazität geringfügig auf runden ihre nächste größere interne "Brockengröße", mit dem Ergebnis, dass die Die Kapazität endet tatsächlich etwas größer als die Größe.
Wie das funktioniert, ist wahrscheinlich vollständig implementierungsdefiniert. Im Gegensatz zu Containern wie Vektor können Strings sehr unterschiedliche Implementierungen haben.
Wenn die String-Implementierung eine kleine String-Optimierung verwendet, kann die Kapazität nicht über einen bestimmten Schwellenwert hinaus verringert werden. Wenn die Zeichenfolgenimplementierung Copy-on-Write verwendet, erfolgt kein Schreibvorgang und keine echte Kopie.
Nach Ссылка sind Shrink-to-Fit und Clear-Complete verschiedene Tricks. Wenn die Absicht ist, vollständig zu löschen, kann erwartet werden, dass ein Austausch mit einer standardkonstruierten Zeichenfolge bessere Ergebnisse liefert.