2016-06-02 6 views
7

Lassen Sie uns sagen, ich habe ein map<int, int>:Ist emplace für grundlegende Typen es wert?

std::map<int, int> map; 

map.emplace(1, 2); 
map.insert({3, 4}); 

keinen Unterschied zwischen den beiden Anrufen da sein?

Im ersten Aufruf werden die beiden Ganzzahlen nach Wert in die emplace-Funktion und dann wieder in den std::pair<int, int>-Konstruktor kopiert. Im zweiten Aufruf werden die zwei Ganzzahlen durch den Wert in den std::pair<int, int>-Konstruktor kopiert und dann als Mitglieder des ersten Paares wieder als Wert in das interne std::pair<int, int> kopiert.

Ich verstehe die Vorteile von emplace für Typen wie std::string, wo sie von Wert im zweiten Aufruf kopiert und den ganzen Weg in der ersten verschoben würden, aber gibt es einen Vorteil bei der Verwendung von emplace in der beschriebenen Situation?

Antwort

11

Emplace ist langsamer, wenn die Möglichkeit besteht, dass der Emplace fehlschlägt (der Schlüssel ist bereits vorhanden).

Das ist, weil emplace erforderlich ist, um einen Knoten zuzuweisen und die pair<Key const, Value> in es zu erstellen, extrahieren Sie den Schlüssel von diesem Knoten und überprüfen Sie, ob der Schlüssel bereits vorhanden ist, dann den Knoten freigeben, wenn der Schlüssel bereits vorhanden ist. Auf der anderen Seite kann insert den Schlüssel aus dem übergebenen Wert extrahieren, so dass kein Knoten zugeordnet werden muss, wenn das Einfügen fehlschlagen würde. Siehe: performance of emplace is worse than check followed by emplace.

Um dies zu beheben, C++ 17 fügt eine Memberfunktion try_emplace(const key_type& k, Args&&... args) (etc.)

Bei Erfolg gibt es keinen wirklichen Unterschied zwischen den beiden Fällen; Die Reihenfolge der Vorgänge ist unterschiedlich, dies beeinträchtigt jedoch die Leistung in keiner vorhersagbaren Weise. Die Codegröße ist für die Variante emplace immer noch etwas größer, da sie bereit sein muss, im Fehlerfall mehr Arbeit zu leisten.