Wann sollte ich std :: map :: at verwenden, um das Kartenelement abzurufen
Habe ich gelesen, die anderen Artikel auf dem web und Fragen an stackoverflowaber für mich ist es nicht klar gibt es eine exklusive Fall, wenn es besser ist, zu verwenden std::map::at
abrufen map-element.
Laut definitionstd::map::at
Gibt einen Verweis auf das zugeordnete Wert des Elements identifiziert
der Schlüssel k.Wenn k nicht mit dem Schlüssel von jedem element in dem container, der
die Funktion wirft eine out_of_range Ausnahme.
Für mich nur dann, wenn es Wert ist zu verwenden std::map::at
wenn Sie 100% sicher sein, das element mit bestimmten Schlüssel existiert, ansonsten sollten Sie überlegen, die Behandlung von Ausnahmen.
- Gibt es irgendeinen Fall, wo
std::map::at
als die meisten effiziente und elegante Art und Weise zu tun? In welchen Fällen empfehlen die Verwendung vonstd::map::at
? - Bin ich richtig, dass es besser ist, zu verwenden
map::find()
wenn es eine Möglichkeit gibt, um nicht-element mit einem solchen Schlüssel? Undmap::find()
es ist schneller und eleganter Ansatz?
if ( map.find("key") != map.end() ) { //found } else { //not found }
p.s
map::operator[]
manchmal gefährlich sein kann, denn wenn ein element nicht existiert, dann wird er es fügt.
BEARBEITET: links, die irgendwie im Zusammenhang link 1 link 2 link 3 link 4 link 5 link 6
InformationsquelleAutor der Frage T M | 2015-10-20
Du musst angemeldet sein, um einen Kommentar abzugeben.
Im Gegensatz zu den meisten bisherigen Antworten hier, beachten Sie, dass es gibt tatsächlich 4 Methoden für das finden eines Elements in einer Karte (ignorieren
lower_bound
upper_bound
undequal_range
die sind weniger präzise):operator[]
existieren nur in nicht-const-version, wie erwähnt, es wird das element anlegen wenn Sie nicht vorhanden istat()
eingeführt, die in C++11 gibt eine Referenz auf das element, wenn es existiert, und wirft andernfalls eine exceptionfind()
gibt einen iterator auf das element, wenn es vorhanden ist, oder ein iterator zumap::end()
wenn es nichtcount()
gibt die Anzahl der Elemente, die in einemmap
ist dies 0 oder 1Nun, dass die Semantik ist klar, lassen Sie uns überprüfen, Wann welcher zu benutzen:
map
(oder auch nicht), dann verwenden Siecount()
.map
dann verwenden Sieat()
.map
oder nicht, dann verwenden Siefind()
; vergessen Sie nicht, um zu überprüfen, dass die entstehende iterator wird nicht gleich das Ergebnis desend()
.operator[]
; wenn Sie nicht mitgehen möchten, die Art default-Konstruktor zu erstellen, dann verwenden Sie entwederinsert
oderemplace
entsprechendInformationsquelleAutor der Antwort Matthieu M.
std::map::at()
wirft einout_of_range
Ausnahme, wenn das element nicht gefunden werden konnte. Diese Ausnahme ist eine Art vonlogic_error
Ausnahme, die für mich eine Art synonym vonassert()
aus der Nutzung Standpunkt: es sollte verwendet werden, um Fehler in der internen Logik des Programms, wie die Verletzung der logischen Voraussetzungen oder Klasse von Invarianten.Können Sie auch
at()
Zugriff auf const-Karten.Also, zu Ihren Fragen:
at()
statt[]
beim Zugriff auf const-maps und wenn das element Abwesenheit ist ein Logik Fehler.map::find()
wenn Sie sich nicht sicher, element ist hier: in diesem Fall ist es nicht ein logischer Fehler und damit das werfen und fangenstd::logic_error
Ausnahme wird nicht sehr elegante Art der Programmierung, auch wenn wir nicht darüber nachdenken Leistung.InformationsquelleAutor der Antwort alexeykuzmin0
Als Sie bemerkte, gibt es drei verschiedene Möglichkeiten, den Zugriff auf Elemente in einer map:
at()
operator[]
undfind()
(es gibt auchupper_bound
lower_bound
undequal_range
diese sind aber für kompliziertere Situationen, in denen Sie möglicherweise suchen Sie ein nächsten/vorherigen element etc.)So, wenn Sie verwenden sollten, welches wäre das?
operator[]
im Grunde ist "wenn es nicht vorhanden ist, erstellen Sie mit ein default-konstruiertes element zugeordnet". Das bedeutet, dass er nicht werfen (außer in den Ausnahmefällen, wenn die Speicherzuordnung wirft oder einer der Schlüssel oder Wert-Konstruktoren werfen), und man bekommt eine Referenz auf das element, das Sie suchten - entweder die bestehende oder die neu erstellt werden.at()
wirft, wenn es kein element für diesen Schlüssel. Da sollten Sie nicht verwenden exceptions für den normalen Programmfluss, mitat()
sagt: "ich bin sicher, dass es ein solches element." Aber mit dem zusätzlichen Vorteil, dass Sie eine Ausnahme (und nicht zu undefiniertem Verhalten), wenn Sie falsch sind. Verwenden Sie nicht dieses, wenn Sie nicht positiv ist, dass das element vorhanden ist.find()
sagt: "es kann nicht sein, ein solches element, mal sehen..." und bietet Ihnen die Möglichkeit, zu reagieren, beide Fälle unterschiedlich. Es ist daher der allgemeinere Ansatz.InformationsquelleAutor der Antwort Arne Mertz
Alle 3
find
operator[]
undat
nützlich sind.find
ist gut, wenn Sie nicht möchten, dass versehentlich Elemente einfügen, sondern nur handeln, wenn Sie vorhanden sind.at
ist gut, wenn Sie erwarten, dass etwas auf eine Karte, und Sie würden eine exception werfen, wenn es nicht sowieso. Es können auch aufconst
Karten in einer knapperen Angelegenheit alsfind
(wo Sie nicht verwenden könnenop[]
)op[]
ist gut, wenn Sie wollen einfügen, um ein Standard-element, wie für die Wort-zähl-Programm, das setzt eine int -0
für jedes Wort begegnet zum ersten mal (mit dem idiomwords[word]++;
).InformationsquelleAutor der Antwort Bartek Banachewicz
Diese hängt davon ab, was die Anforderungen sind für diese Funktion und wie sind Sie strukturieren das Projekt. Wenn Sie werden sollte ein Objekt zurückgeben, und Sie können nicht, weil es nicht gefunden wurde, dann ist es lässt Sie mit zwei Optionen auf, wie damit umzugehen ist. Sie könnte durch eine Ausnahme-oder Sie zurückgeben könnte, irgendeine Art von sentinel das bedeutet, dass nichts gefunden wurde. Wenn Sie möchten, eine exception werfen, dann verwenden Sie
at()
als die exception wird geworfen, für Sie. Wenn Sie nicht möchten, dass eine exception werfen, dann verwenden Siefind()
so dass Sie nicht haben, um mit der Handhabung einer Ausnahme nur um wieder eine sentinel-Objekt.InformationsquelleAutor der Antwort NathanOliver
Ich denke, es hängt von Ihrem Anwendungsfall. Der Rückgabetyp
std::map::at()
ist ein lvalue-Referenz auf den Wert des gefundenen Elements, währendstd::map::find()
gibt einen iterator. Sie könnten es vorziehen,in äußerungen über die aufwändigere
Wann immer Sie das Ergebnis verwenden von
std::map::at()
in einem Ausdruck, die Sie erwarten, dass das element vorhanden ist, und betrachten ein element fehlt, als ein Fehler. So eine Ausnahme ist eine gute Wahl, damit umzugehen.InformationsquelleAutor der Antwort cdonat
Ich denke, der Unterschied ist Semantik.
std::map::at()
aussieht wie das auf meiner Maschine:Wie Sie sehen können, verwendet es
lower_bound
dann prüftend()
vergleicht Schlüssel, und wirft die Ausnahme, wo nötig.find()
sieht wie folgt aus:wo
_M_t
ist ein rot-schwarz-Baum, der speichert die eigentlichen Daten. Offensichtlich, die beide die Funktion haben, die gleichen (logarithmischen) Komplexität. Wenn Siefind()
+ check fürend()
Sie tun fast das gleiche, wasat
tut. Ich würde sagen, der semantische Unterschied ist:at()
wenn Sie brauchen, ein element an einem bestimmten Ort, und Sie davon ausgehen, dass es da ist. In diesem Fall wird die situation der das element fehlt, aus dem gewünschten Ort ist außergewöhnlich, soat()
wirft eine Ausnahme.find()
wenn Sie brauchen, um zu finden das element in der Karte. In diesem Fall ist die situation, wenn das element nicht vorhanden ist, ist normal. Beachten Sie auch, dassfind()
gibt einen iterator, die Sie verwenden können, für andere Zwecke als nur die Beschaffung ist es Wert.InformationsquelleAutor der Antwort SingerOfTheFall
map::at() liefert einen l-Wert-Referenz, und wenn Sie die Rückgabe durch Referenz verwenden, können Sie alle verfügbaren Vorteile, wie z.B. die Verkettung von Methoden.
Beispiel:
operator[]
auch gibt den zugeordneten Wert durch Referenz, aber Sie können fügen Sie einen Wert, wenn der gesuchte Schlüssel nicht gefunden wird, in dem Fall container Größe um eins erhöht.Dies erfordert, dass Sie besonders vorsichtig sein, da Sie zu kümmern iterator-Invalidierung.
Ja, semantisch macht es Sinn, find (), wenn Sie nicht sicher sind, von der Existenz element.Macht den code leichter zu verstehen, auch für Anfänger.
Als für die Zeit, die Effizienz, die Karte ist in der Regel umgesetzt werden, da ein RB-Baum/eine ausgewogene binären Suchbaum und damit die Komplexität ist O(logN) für die find().
InformationsquelleAutor der Antwort basav