Ich habe mit C ++ - Konstruktoren herumgespielt. Hier ist mein Code:
%Vor%Die Ausgabe ist:
%Vor%Die ersten drei Zeilen zeigen an, dass die lokale Variable in der Funktion foo () mit Konstruktor erstellt und zerstört wird, wenn foo () zurückkehrt. Die vierte Zeile zeigt an, dass b mithilfe von move-Konstruktor erstellt wurde. Aber die nächsten zwei Zeilen sind am verwirrendsten: Ich habe jetzt eine neue Adresse, die sich von der lokalen Variable "a" in foo () unterscheidet, die ich benutzt habe, um den Move-Konstruktor aufzurufen. Wenn der Kopierkonstruktor beendet ist, verschwindet die rvalue-Referenz und der Destruktor wird aufgerufen. Aber warum gibt es keinen Kopierkonstruktor für 0x7fff5d97bbc0? Mit anderen Worten, woher kommt 0x7fff5d97bbc0 und wie wird es aufgebaut? Es ist einfach verdrahtet, dass es noch einen Destruktor gibt, der als Konstruktor bezeichnet wird.
Ich habe das Gefühl, dass dies etwas mit Kopier-Elision zu tun hat. Also habe ich die Rückleitung in foo () in folgendes geändert:
%Vor%Und die Ausgabe ist:
%Vor%Jetzt hat es endlich einen Sinn ergeben: In der dritten Zeile wird angezeigt, dass der Kopierkonstruktor aufgerufen wird, bevor "a" zerstört wird. Dies bedeutet, dass bei der Rückgabe als Wert der Wert tatsächlich in den Rückgabewert kopiert wurde, bevor die temporäre Variable gelöscht wurde.
Aber ich war immer noch verwirrt durch das ursprüngliche Programm (ohne std :: move ()), denn wenn es wirklich durch copy elision verursacht wird, sollte nicht die Adresse des Rückgabewerts von foo () mit der lokalen Variable übereinstimmen "ein"? Nun, da es anders ist, was bedeutet, dass es an einer völlig anderen Position im Speicher von "a" lokalisiert wird, warum hat es dann den Kopierkonstruktor nicht aufgerufen?
Ich hoffe, meine Frage ist klar und verständlich.
Bearbeiten: Der Compiler, den ich verwendet habe, war clang ++ mit dem Flag -fno-elide-constructors.
Was ist Ihr Compiler, ohne den std::move
zu klauen:
mit dem std::move
:
Diese beiden Ergebnisse sind viel logischer als Ihre, also noch einmal, was ist Ihr Compiler?
Bearbeiten: Es schmeckt wie ein Fehler mit der Flagge -fno-elide-constructors.
durch Hinzufügen eines int-Members nach den zwei ursprünglichen Membern, dasselbe Ergebnis, aber wenn der int zuerst ist, Speicherbeschädigung! Und die Non-Corruption-Version endet mit einem nullptr-Wert im ArrayWrapper. Sehen Sie sich das Protokoll "und löschen" an, um das fehlerhafte Verhalten zu erkennen.
Ссылка & lt; - int nach, ok
Ссылка & lt; - int vorher, Korruptionsdump
Tags und Links c++ c++11 move-semantics copy-constructor copy-elision