2016-06-10 4 views
9

Die einfache Lösung existiert, ist obviosulyeffiziente Art und Weise eine unique_ptr in eine Karte einfügen, ohne den Zeiger zu löschen, wenn der Schlüssel bereits

std::map<int,std::unique_ptr<something>> mymap; 

auto f = mymap.find(5); 
std::unique_ptr<something> myptr; 

if (f == mymap.end()) 
    mymap.insert({5, std::move(myptr)}); 

Dies ist jedoch nicht zu effizient sieht, wie ich den Schlüssel zu finden, in der Karte zweimal. Ein, um zu überprüfen, ob der Schlüssel nicht existiert, und die Einfügefunktion wird das gleiche tun.

Wenn ich einfach mymap.insert({5, std::move(myptr)}); verwende, dann ist mein eindeutiges ptr (myptr) weg, wenn pair.second false zurückgibt (Schlüssel existiert bereits).

EDIT:

Anscheinend ist die Antwort auf C 17 ++, mit try_emplace, und es ist bereits in dem Compiler Ich verwende (vs2015) und da ich an einem persönlichen Projekt gerade arbeite, kann ich leisten, es zu benutzen.

+1

Warum sagen Sie es nicht effizient aus? Sieht gut aus für mich. –

+0

Wenn Sie sich Sorgen machen über die Komplexität von 'std :: map :: find', dann verwenden Sie vielleicht den falschen Container? 'std :: unordered_map' sitzt auf einer Hashtabelle, wodurch einige Operationen O (1) amortisiert statt O (log n) werden - find included. – Conduit

+6

Sieht so aus, als ob Sie das nächste im nächsten Standard haben möchten ['try_emplace'] (http://en.cppreference.com/w/cpp/container/map/try_emplace) – NathanOliver

Antwort

5

Wenn Sie nicht speichern nullptr s in der Karte gehen, dann können Sie es wie folgt tun:

auto& r = mymap[5]; 
if (r == nullptr) 
    r = std::move(myptr); 
+1

Das ist eine sehr interessante Idee! – James

0

Vielleicht den Kontext Ich verstehe nicht ganz, aber warum etwas zu bewegen und es nicht einzulagern?

std::map<int,std::unique_ptr<something>> mymap; 

auto f = mymap.find(5); 

if (f == mymap.end()) 
    mymap.emplace(5, std::make_unique<something>(myptr)); 
+1

Die Suche wird zweimal durchgeführt, genauso wie das ursprüngliche OP-Snippet. –

2

Der Standard Trick ist, für die Einfügemarke suchen:

auto f = mymap.lower_bound(5); 
if ((f == mymap.end()) || mymap.key_comp()(5, f->first)) { 
    mymap.insert(f, {5, std::move(myptr)}); // or mymap.emplace_hint(f, 5, std::move(myptr)) 
} 
Verwandte Themen