Leistung der Deklaration von Objekten

Jan 03 2021

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

2 dxiv Jan 04 2021 at 10:59

In der ersten Version des Codes werden der Konstruktor und der Destruktor von mal hashMapaufgerufen 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 mapObjekts sich deutlich vom Löschen und Wiederverwenden ein und desselben Objekts unterscheidet. Dies kann definitiv nur beantwortet werden, indem der tatsächliche mapCode 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 cleara mapstattdessen 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 mapvon abgeleitet sind _Tree, wird dies jedes Mal aufgerufen, wenn ein mapObjekt erstellt wird.