2016-05-05 18 views
8

Ist der Punkt, an dem std::map::emplace erstellt das Objekt (d. H. Aufruf des Konstruktors) irgendwie in Standard angegeben? Wenn ja, passiert es vor Vorhandensein eines solchen Schlüssels überprüft oder nach?An welchem ​​Punkt erstellt map :: emplace ein Objekt?

Es spielt eine große Rolle in den Fällen wie folgt vor:

struct X {}; 
std::map<int, std::unique_ptr<X> > map; 

void f(int x) { 
    map.emplace(x, new X); 
} 

Wenn das Objekt zum ersten Mal erstellt wird, werden alle cool (unique_ptr ist so aufgebaut und besitzt die Ressource), aber wenn es nach der Prüfung aufgebaut ist, gibt ist ein Speicherverlust im Falle eines doppelten Schlüssels.

Alles in Standard-finden Ich war in der Lage ist

Fügt ein t value_type Objekt konstruiert mit std::forward<Args>(args)..., wenn und nur wenn kein Element in der zu dem Schlüssel von t Behältern mit Schlüssel entspricht.

was nicht die Frage, die ich habe.

+8

Die Verwendung von 'new T' in einer Argumentliste ist sowieso schlecht, also lautet die" echte "Antwort Do not Do That. Verwenden Sie 'make_unique ()' und jetzt leckt es nie. – GManNickG

+1

In jedem Fall tritt ein Leck auf, wenn die Zuweisung fehlschlägt. –

+1

Sie platzieren Smart Pointer normalerweise nicht, weil das Kopieren/Verschieben schnell und sicher ist. Ihre Frage würde mehr Sinn ergeben, wenn es sich um eine 'map ' – Fozi

Antwort

12

Dies ist in der Tat unterspezifiziert, das ist teilweise warum C++ 17 try_emplace hinzugefügt, um die Semantik zu nageln. N3873, eine frühe Version des try_emplace Vorschlag, hat eine gute Diskussion über die bestehende Formulierung.

Im allgemeinen Fall muss es "vorher" sein, da "nachher" nicht ausführbar ist, und der Standard wäre fehlerhaft, wenn er eine solche Anforderung auferlegt. Betrachten Sie emplace(piecewise_construct, forward_as_tuple(foo, bar), forward_as_tuple(meow, purr)). Da der Schlüssel und der Wert nicht beweglich sein müssen, müssen Sie das Objekt zuerst konstruieren und die Existenz des Schlüssels überprüfen, da Sie nicht ohne den Schlüssel nach dem Vorhandensein des Schlüssels suchen können.

Es ist jedoch nicht undenkbar, dass eine Implementierung einen speziellen Fall wünschen könnte: emplace(key_type, something); Es ist in der Regel eine gute Sache zu vermeiden, für die erforderliche Zuweisung zu zahlen + Konstruktion + Zerstörung + Freigabe, wenn der Schlüssel existiert.

+0

Komplett und sehr lehrreich, wie immer. – SergeyA

Verwandte Themen