prestazioni di dichiarazione di oggetti

Jan 03 2021

Stavo programmando una sorta di conquista universitaria e ho notato qualcosa, quando dichiaro una mappa in un ciclo come in basso:

for (int i = 0; i < n; i++)
{
    map<int, bool> hashMap;
    //...
}

ci vuole più tempo di:

map<int, bool> hashMap;
for (int i = 0; i < n; i++)
{
    hashMap.clear();
    //...
}

quindi mi chiedevo perché la dichiarazione di un oggetto in un ciclo ha prestazioni peggiori rispetto alla semplice reinizializzazione?

Risposte

2 dxiv Jan 04 2021 at 10:59

Nella prima versione del codice il costruttore e il distruttore del hashMapsono chiamati ntempi, mentre nella seconda versione sono chiamati una sola volta.

La domanda naturale è perché la distruzione e la costruzione di un nuovo mapoggetto sarebbero notevolmente diverse rispetto alla pulizia e al riutilizzo di uno stesso oggetto. Questo può essere risolto definitivamente solo ispezionando il mapcodice effettivo dell'implementazione utilizzata, quindi quanto segue è solo un'ipotesi plausibile.

std::mapdi solito è implementato utilizzando alberi rosso-nero , ed è comune per le implementazioni albero rosso-nero utilizzare un nodo sentinella per foglie NIL, vedere ad esempio Vantaggi di un nodo sentinella in un albero rosso nero? . Questa sentinella deve essere assegnata ogni volta che viene costruito un albero, quindi rilasciata dopo la distruzione. Al contrario, clear'ing a mapsvuota l'albero ma riutilizza gli oggetti interni associati.

Per un esempio reale di tale implementazione, il _Treecostruttore di Microsoft chiama il nome appropriato _Alloc_sentinel_and_proxy();. Poiché mapderivano da _Tree, questo viene chiamato ogni volta mapche viene costruito un oggetto.