Ich habe einen einfachen Testfall erstellt, der ein merkwürdiges Verhalten zeigt, das mir in einer größeren Codebasis aufgefallen ist, an der ich gerade arbeite. Dieser Testfall ist unten. Ich verlasse mich auf den Operator "[]" der STL-Map, um einen Zeiger auf eine Struktur in einer Map solcher Strukturen zu erzeugen. Im folgenden Testfall ist die Zeile ...
%Vor%... holt mir den Zeiger (und erstellt einen neuen Eintrag in der Karte). Das Seltsame, was ich bemerkt habe, ist, dass diese Zeile nicht nur einen neuen Eintrag in der Map erzeugt (wegen des Operators "[]"), sondern aus irgendeinem Grund den Destruktor der Struktur zwei zusätzliche Male aufgerufen wird. Ich vermisse offensichtlich etwas - jede Hilfe wird sehr geschätzt! Danke!
%Vor%Der obige Code gibt folgendes aus ...
%Vor%... aber ich verstehe nicht, was die ersten zwei Aufrufe von Destructor von TestStruct verursacht? (Ich denke, dass der letzte Destruktoraufruf sinnvoll ist, weil testStructMap den Gültigkeitsbereich verlässt.)
Die Funktionalität von std::map<>::operator[]
entspricht
Ausdruck, wie in der Sprachspezifikation angegeben. Wie Sie sehen können, wird dabei standardmäßig ein temporäres Objekt vom Typ T
erstellt und in ein std::pair
-Objekt kopiert, das später (wieder) in das neue Element der Map kopiert wird (vorausgesetzt, es war nicht dort) bereits). Offensichtlich werden dadurch einige intermediate T
-Objekte erzeugt. Die Zerstörung dieser Zwischenobjekte beobachten Sie in Ihrem Experiment. Sie vermissen ihre Konstruktion, da Sie keine Rückmeldungen vom Copy-Konstruktor Ihrer Klasse erhalten.
Die genaue Anzahl der Zwischenobjekte hängt möglicherweise von den Optimierungsfunktionen des Compilers ab, daher können die Ergebnisse variieren.
Sie haben einige ungesehene Kopien gemacht:
%Vor%Ergebnisse in:
%Vor% Ihre zwei mysteriösen Destruktor-Aufrufe werden wahrscheinlich mit Kopier-Konstruktor-Aufrufen gepaart, die irgendwo in der std::map
stattfinden. Zum Beispiel ist es denkbar, dass operator[]
standardmäßig ein temporäres TestStruct
-Objekt erstellt und es dann an die richtige Stelle in der Map kopiert. Der Grund dafür, dass es zwei Destruktoraufrufe (und somit wahrscheinlich zwei Aufrufe von Kopierkonstruktoren) gibt, ist implementierungsspezifisch und hängt von Ihrem Compiler und der Implementierung der Standardbibliothek ab.
operator[]
fügt in map
ein, wenn dort noch kein Element vorhanden ist.
Was Ihnen fehlt, ist die Ausgabe für den vom Compiler gelieferten Kopierkonstruktor in Ihrer TestStruct
, die während der Containerverwaltung verwendet wird. Fügen Sie diese Ausgabe hinzu, und alles sollte sinnvoller sein.
BEARBEITEN: Andreys Antwort hat mich dazu veranlasst, einen Blick auf die Quelle von% VC_10% von Microsoft VC ++ 10 zu werfen, was Sie auch tun könnten, um dies in all seinen blutigen Details zu verfolgen. Sie können den <map>
-Aufruf sehen, auf den er sich bezieht.
Sie können es durch diesen einfacheren Code überprüfen.
%Vor%Das folgende Ergebnis zeigt, dass der obige Zeilencode (1 default const) und (2 default copy const) aufruft.
%Vor%Tags und Links c++ constructor stl copy-constructor temporary-objects