Warum erzwingt std :: vector die Kopie bei der Initialisierung?

8

Ich habe eine Kopier- / Verschiebeprüfklasse:

%Vor%

Und ich habe festgestellt, dass running:

%Vor%

Erzeugt die folgende Ausgabe:

%Vor%

Warum wird die Initialisierung nicht einfach die Objekte verschieben? Ich weiß, dass std::vector unerwünschte Kopien bei der Größenänderung erstellen kann , aber wie Sie sehen können, hat das Hinzufügen von noexcept hier nicht geholfen (und außerdem glaube ich nicht, dass die Gründe für die Größenänderung zur Initialisierung führen).

Wenn ich stattdessen Folgendes tue:

%Vor%

Ich bekomme keine Kopien.

Getestet mit GCC 5.4 und Clang 3.8.

    
jdehesa 17.07.2017, 11:26
quelle

1 Antwort

9

Dies ist nicht std::vector , sondern std::initializer_list .

std::initializer_list wird von einem const Array von Elementen unterstützt. Es erlaubt nicht% const Zugriff auf seine Daten.

Dies blockiert die Bewegung von seinen Daten.

Aber das ist C ++, also können wir das lösen:

%Vor%

Jetzt bekommen wir:

%Vor%

gibt Ihnen 1 zusätzliche Bewegung pro Element:

%Vor%

Wir können diese Extra-Instanz mit einem sorgfältigen Reservierungs- und Einrückungs-Schritt eliminieren:

%Vor%

Live-Beispiel von beiden - tausche einfach v2:: gegen v1:: , um den ersten zu sehen Aktion.

Ausgabe:

%Vor%

es könnte ein bisschen mehr Vektor-Overhead hier sein, da es für den Compiler schwierig sein kann zu beweisen, dass emplace_back keine Neuzuweisung verursacht (obwohl wir es beweisen können), so dass redundante Tests höchstwahrscheinlich kompiliert werden. (Meiner Meinung nach brauchen wir eine emplace_back_unsafe , die UB ist, wenn die Kapazität nicht ausreicht).

Der Verlust der zusätzlichen Menge von A s ist es wahrscheinlich wert.

Eine andere Wahl:

%Vor%

welches wie

benutzt wird %Vor%

Hier müssen Sie angeben, wie viele Elemente manuell eingegeben werden sollen. Es ist so effizient wie die Version 2 oben.

    
Yakk 17.07.2017, 14:53
quelle

Tags und Links