Leistung der Deklaration von Objekten
Ich habe in einer Art Universitätseroberung programmiert und etwas bemerkt, als ich eine Karte in einer Schleife wie unten deklarierte:
for (int i = 0; i < n; i++)
{
map<int, bool> hashMap;
//...
}
Es dauert länger als:
map<int, bool> hashMap;
for (int i = 0; i < n; i++)
{
hashMap.clear();
//...
}
Ich habe mich gefragt, warum das Deklarieren eines Objekts in einer Schleife eine schlechtere Leistung hat, als es nur neu zu initialisieren.
Antworten
In der ersten Version des Codes werden der Konstruktor und der Destruktor von mal hashMap
aufgerufen n
, während sie in der zweiten Version nur einmal aufgerufen werden.
Die natürliche Frage ist, warum das Zerstören und Konstruieren eines neuen map
Objekts sich deutlich vom Löschen und Wiederverwenden ein und desselben Objekts unterscheidet. Dies kann definitiv nur beantwortet werden, indem der tatsächliche map
Code der verwendeten Implementierung überprüft wird. Das Folgende ist also nur eine plausible Vermutung.
std::mapwird normalerweise mit rot-schwarzen Bäumen implementiert , und es ist üblich, dass rot-schwarze Baumimplementierungen einen Sentinel- Knoten für NIL-Blätter verwenden, siehe zum Beispiel Nutzen eines Sentinel-Knotens in einem rot-schwarzen Baum? . Dieser Sentinel muss jedes Mal zugewiesen werden, wenn ein Baum erstellt wird, und dann bei Zerstörung freigegeben werden. Im Gegensatz dazu leert clear
a map
stattdessen den Baum, verwendet jedoch die zugehörigen internen Objekte wieder.
Für ein reales Beispiel einer solchen Implementierung _Treenennt der Microsoft- Konstruktor den treffend benannten _Alloc_sentinel_and_proxy();
. Da sie map
von abgeleitet sind _Tree
, wird dies jedes Mal aufgerufen, wenn ein map
Objekt erstellt wird.