Temporäre Objekte in einen Vektor verschieben

8
%Vor%

Das obige Beispiel erzeugt die nächste Ausgabe:

%Vor%

Fragen:

  1. Warum wird der 1. Destruktor ausgeführt (wird aber für das 2. Objekt nicht ausgeführt)?
  2. Warum wird das 2. Objekt bewegt, bevor das 1. Objekt bewegt wird?
  3. Warum werden am Ende zwei Destruktoren für jedes Objekt ausgeführt?

PS Ich habe gerade überprüft, und die Objekte sind tatsächlich wie erwartet platziert (der erste geht auf die Position 0 im Vektor, und der zweite geht auf die Position 1 im Vektor)

PPS Wenn es darauf ankommt, verwende ich gcc 4.3 und kompiliere das Programm wie folgt:

%Vor%     
BЈовић 06.10.2011, 08:12
quelle

4 Antworten

8

Ich habe Ihr Beispiel leicht umgeschrieben:

%Vor%
  1. Ich habe const aus dem Move-Konstruktor entfernt.
  2. Ich habe std::move aus push_back entfernt (es ist überflüssig).
  3. Ich habe Markierungen zwischen den Aufrufen von foo eingefügt.

Für mich druckt das ähnlich wie Ihr Code:

%Vor%
  
  1. Warum wird der erste Destruktor ausgeführt (wird aber nicht ausgeführt für den   2. Objekt)?
  2.   

Der 2. Destruktor wird für das 2. Objekt an der mit // 1 markierten Zeile ausgeführt. Dies ist die Zerstörung des temporären A() am Ende des zweiten Aufrufs von push_back .

  
  1. Warum wird das 2. Objekt bewegt, vor dem Verschieben des 1. Objekts ausgeführt?   Objekt?
  2.   

Hinweis: Für mich wird das 1. Objekt kopiert, nicht verschoben, mehr dazu unten.

Antwort: Ausnahmesicherheit.

Erklärung: Während dieser push_back entdeckt der Vektor, dass er einen vollen Puffer (von eins) hat und einen neuen Puffer mit Platz für zwei erstellen muss. Es erstellt den neuen Puffer. Dann verschiebt das zweite Objekt in diesen Puffer (am Ende davon). Wenn diese Konstruktion eine Ausnahme auslöst, ist der ursprüngliche Puffer immer noch intakt und das vector bleibt unverändert. Andernfalls werden die Elemente vom ersten Puffer zum zweiten Puffer verschoben oder kopiert (also das erste Element verschieben / kopieren).

Wenn A einen noexcept move-Konstruktor hat, wird ein move verwendet, um ihn vom alten in den neuen Puffer zu verschieben. Wenn der Move-Konstruktor jedoch nicht noexcept ist, wird ein copy verwendet. Dies ist wiederum für Ausnahmesicherheit. Wenn die Bewegung vom alten zum neuen Puffer fehlschlagen kann, muss der alte Puffer intakt bleiben, damit der vector in seinen ursprünglichen Zustand zurückversetzt werden kann.

Wenn ich noexcept zu Ihrem Move-Konstruktor hinzufüge:

%Vor%

Dann ist meine Ausgabe:

%Vor%

Beachten Sie, dass die mit // 2 markierte Zeile die Zerstörung des ersten Elements aus dem alten Puffer ist, nachdem es in den neuen Puffer verschoben wurde.

  
  1. Warum werden am Ende zwei Destruktoren für jedes Objekt ausgeführt?
  2.   

Dies markiert die Zerstörung von vector und somit die Zerstörung jedes Elements von vector .

    
Howard Hinnant 06.10.2011, 13:08
quelle
5

Die vernünftige Verwendung von reserve löst die Hälfte Ihres Problems: Ссылка indem Sie die Anzahl der unerwarteten Bewegungen reduzieren ( dass du nicht explizit darum bittest)

Vergessen Sie auch nicht, dass der Destruktor des Temps weiterhin auslöst, nachdem in den Vektor verschoben wurde. Deshalb müssen Sie sicherstellen, dass die Temp auch nach dem Verschieben / Konstruieren im gesunden , zerstörbaren Zustand bleibt.

%Vor%     
sehe 06.10.2011 08:23
quelle
4

Der Vektor erhöht seine Kapazität und verschiebt die internen Elemente während des Aufrufs in push_back .

    
dalle 06.10.2011 08:18
quelle
2

Ein Verschiebungskonstruktor "zerstört" das verschobene Objekt nicht.

%Vor%

Die Ausgabe ergibt:

%Vor%     
Matthieu M. 06.10.2011 08:24
quelle

Tags und Links