2013-06-08 6 views

Antwort

46

Absatz C.2.12 des Anhang C (Kompatibilität) zu dem Standard spezifiziert 11 ++ C:

ändern: Unterschrift Änderungen: resize

Rationale: Performance, Kompatibilität mit Bewegung Semantik.

Wirkung auf die ursprüngliche Funktion: Für vector, deque und list der Füllwerts wird nun durch Verweis anstelle von Wert und eine zusätzliche Überlast von Resize hinzugefügt wurde weitergegeben, um die Größe übergeben. Gültiger C++ 2003-Code , der diese Funktion verwendet, kann möglicherweise nicht mit dieser Internationalen Norm kompilieren.

Die alte resize()-Funktion war Kopieren-Konstruieren neuer Elemente von value. Dies macht es unmöglich, resize() zu verwenden, wenn die Elemente des Vektors default-constructible, aber nicht-kopierbar sind (Sie könnten sie später verschieben wollen). Dies erklärt die "Kompatibilität mit Bewegungssemantik" Begründung.

Darüber hinaus kann es langsam sein, wenn Sie keine Kopie auftreten möchten, nur neue Elemente standardmäßig erstellt werden. Außerdem wird der value-Parameter in der C++ 03-Version als Wert übergeben, was zu einer unnötigen Kopie führt (as mentioned by TemplateRex in his answer). Dies erklärt die Begründung "Leistung".

+0

Schön. Kannst du jetzt ein Beispiel finden, wo dies den bestehenden Code aufbrechen würde? –

+0

@KonradRudolph Es sollte abwärtskompatibel sein. Die erste C++ 11-Überladung entspricht in C++ 98 dem zweiten Argument nicht, und die zweite C++ 11-Überladung erfordert nur Constructible, das C++ 98 bereits für die Größenänderung benötigt. Oder fehlt mir etwas? – TemplateRex

+0

@TemplateRex Das Standardzitat in dieser Antwort besagt explizit, dass dies nicht der Fall ist: "Gültiger C++ 2003-Code, der diese Funktion verwendet, kann nicht kompiliert werden". –

16

Einen Grund dafür ist, dass Standard-Argumente immer bestanden, dh in diesem Fall kopiert. Doing

my_vector.resize(1000000) 

würde 1 Million T Objekte kopieren.

In C++ 11 haben Sie jetzt die Wahl zwischen dem Kopieren eines vom Benutzer bereitgestellten Werts oder dem Einfügen (d. H. Dem Erstellen) von Elementen an Ort und Stelle unter Verwendung der std::allocator_traits<Alloc>::construct()-Funktion. Dies ermöglicht die Größenänderung von vector mit Elementen, die CopyInsertable aber nicht Copyable sind.

Beachten Sie, dass diese Änderung auf alle Sequenzcontainer mit einem resize() Mitglied getan wurde (vector, deque, forward_list und list), aber nicht für std::string, die keinen Standardwert Argument haben zu beginnen.

aktualisieren: Neben der Anlage zur aktuellen Norm von @AndyProwl zitiert, verdeutlicht die original defect report von @HowardHinnant auch:

Das Problem mit T nach Wert vorbei ist, dass es erheblich sein kann mehr teurer als durch Referenz. Das Umgekehrte ist auch wahr, aber wenn es wahr ist, ist es normalerweise weit weniger dramatisch (z. B. für skalare Typen).

Auch wenn die Bewegungssemantik verfügbar ist, kann die Übergabe dieses Parameters nach Wert teuer sein. Betrachten wir zum Beispiel Vektor>:

std::vector<int> x(1000); std::vector<std::vector<int>> v; ... 
v.resize(v.size()+1, x); 

Im Pass-by-Wert Fall wird x einmal kopiert auf den Parameter Größe ändern. Und dann intern, da der Code nicht zur Kompilierzeit wissen, durch wie viel Größe der Vektor wächst, x wird in der Regel ein zweites Mal von resize Parameter in seinen richtigen Platz innerhalb des Vektors kopiert (nicht verschoben).

Mit pass-by-const-referenz muss das x im obigen Beispiel nur einmal kopiert werden. In diesem Fall verfügt x über einen teuren Kopierkonstruktor , sodass alle Kopien, die gespeichert werden können, eine erhebliche Ersparnis darstellen.

Wenn wir für push_back effizient sein können, sollten wir effizient sein für Größe ändern. Die Größenanpassung unter Verwendung eines Referenzparameters wurde mit codiert und in der CodeWarrior-Bibliothek versandt. Es sind keine Berichte über Probleme vorhanden, über die ich weiß .

+0

C++ 11: Macht den Entwicklern! Wir geben * Ihnen * das Recht zu wählen, welche Objekte kopiert werden sollen! –

Verwandte Themen