Warum bewirkt der Operator "[]" in einer STL-Map von Strukturen, dass das dtor der Struktur zwei zusätzliche Male aufgerufen wird?

8

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.)

    
Monte Hurd 25.10.2010, 19:02
quelle

7 Antworten

18

Die Funktionalität von std::map<>::operator[] entspricht

%Vor%

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.

    
AnT 25.10.2010, 19:20
quelle
8

Sie haben einige ungesehene Kopien gemacht:

%Vor%

Ergebnisse in:

%Vor%     
Michael Burr 25.10.2010 19:11
quelle
5

fügen Sie der TestStruct-Schnittstelle folgendes hinzu:

%Vor%     
justin 25.10.2010 19:08
quelle
4

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.

    
John Calsbeek 25.10.2010 19:08
quelle
4

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.

%Vor%     
Steve Townsend 25.10.2010 19:08
quelle
0

Die Lektion lautet also: Stellen Sie keine Strukturen in eine Map, wenn Sie sich um ihre Lebenszyklen kümmern. Verwenden Sie Zeiger oder besser shared_ptrs zu ihnen

    
pm100 25.10.2010 21:19
quelle
0

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%     
cloudrain21 07.12.2016 00:39
quelle