Warum nicht std::map-operator[] ein Objekt erstellen, wenn der Schlüssel nicht vorhanden?
Ich bin mir ziemlich sicher, sah ich diese Frage irgendwo (comp.lang.c++? Google nicht scheinen, um es zu finden gibt), aber eine kurze Suche hier nicht scheinen, es zu finden, also hier ist es:
Warum hat die std::map-operator[] ein Objekt erstellen, wenn der Schlüssel nicht vorhanden? Ich weiß nicht, aber für mich scheint counter-intuitive, wenn man im Vergleich zu den meisten anderen operator[] (wie std::vector), wo, wenn Sie es verwenden, müssen Sie sicher sein, dass der index existiert. Ich Frage mich, was die Beweggründe für die Durchführung dieses Verhalten von std::map. Wie ich schon sagte, wäre es nicht mehr intuitiv zu handeln wie ein index in einem Vektor-und crash (auch zu undefiniertem Verhalten denke ich), wenn der Zugriff mit einem ungültigen key?
Raffination meine Frage nachdem ich die Antworten:
Ok so weit ich habe eine Menge von Antworten sagen im Grunde ist es Billig, also warum nicht oder ähnliche Dinge. Ich Stimme völlig mit, aber warum nicht über eine spezielle Funktion für, die (ich glaube, der Kommentar sagte, dass in java gibt es keinen operator[] und die Funktion aufgerufen wird gestellt)? Mein Punkt ist, warum nicht map-operator[] funktioniert wie ein Vektor? Wenn ich mit operator[] auf eine out-of-range index eines Vektors ich es nicht möchte, um ein element einzufügen auch wenn es Billig warweil das wahrscheinlich bedeuten, einen Fehler in meinem code. Mein Punkt ist, warum es ist nicht das gleiche wie mit der Karte. Ich meine, für mich, über operator[] auf einer Karte, würde das bedeuten: ich weiß, dieser Schlüssel ist bereits vorhanden (aus welchem Grund auch immer, habe ich nur eingefügt, ich habe Redundanz irgendwo, was auch immer). Ich denke, es wäre intuitiver, Weg.
Das heißt, was sind die Vorteil des aktuellen Verhaltens mit operator[] (und nur für diese, ich Stimme zu, dass eine Funktion mit dem aktuellen Verhalten sollte es sein, nur nicht operator[])? Vielleicht gib es übersichtlicher code, der Weise? Ich weiß es nicht.
Andere Antwort war, dass es bereits so, also warum nicht halten Sie es aber dann, wahrscheinlich, wenn Sie (die, die vor AWL) wählen, um es zu implementieren, die Art, wie Sie fand es einen Vorteil, oder was? Also meine Frage ist im Prinzip: warum Sie wählen, um es zu implementieren, die Art und Weise, was bedeutet, eine etwas mangelnde Kohärenz mit anderen operator[]. Was für ein Vorteil es tun zu geben?
Dank
InformationsquelleAutor der Frage n1ckp | 2009-10-28
Du musst angemeldet sein, um einen Kommentar abzugeben.
Weil
operator[]
liefert eine Referenz auf den Wert selbst und so der einzige Weg, um auf ein problem hindeuten würden eine exception werfen (und im Allgemeinen, die STL selten wirft Ausnahmen).Wenn Sie nicht wie dieses Verhalten, können Sie
map::find
statt. Es gibt einen iterator statt der Wert. Dies ermöglicht es, liefern eine spezielle iterator-wenn der Wert nicht gefunden wird (es gibtmap::end
), sondern auch erfordert, dass Sie den iterator dereferenzieren, um auf den Wert.InformationsquelleAutor der Antwort R Samuel Klatchko
Standard sagt (23.3.1.2/1), dass der operator[] liefert die
(*((insert(make_pair(x, T()))).first)).second
. Das ist der Grund. Es gibt ReferenzT&
. Es gibt keinen Weg, um ungültige Referenz. Und es gibt Referenz, weil es sehr bequem ist, denke ich, ist es nicht?InformationsquelleAutor der Antwort Kirill V. Lyadvinsky
Zur Beantwortung Ihrer eigentlichen Frage: es gibt keine überzeugende Erklärung, warum es gemacht wurde, Weg. "Einfach da".
Seit
std::map
ist ein assoziative container, gibt es keine klar vordefinierte Reihe von Tasten, die muss vorhanden sein (oder nicht vorhanden) in der Karte (im Gegensatz zu der völlig anderen situation mitstd::vector
). Das bedeutet, dass mitstd::map
müssen Sie beide nicht insering und einfügen lookup-Funktionalität bereit. Man könnte überlastung[]
im nicht-einsetzen Weise und bieten eine Funktion zum einfügen. Oder man könnte den anderen Weg herum: überlast[]
als ein einfügen operator und eine Funktion für nicht-einfügen-Suche. So, irgendwann einmal jemand entschieden, zu Folgen dem letzteren Ansatz. Das ist alles dort ist zu es.Tat, wenn Sie es anders herum, vielleicht ist heute jemand Fragen, hier die umgekehrte version Ihrer Frage.
InformationsquelleAutor der Antwort AnT
Ist für die Zuordnung Zwecke:
InformationsquelleAutor der Antwort EToreo
Es ermöglicht einfügen von neuen Elementen mit
operator[]
wie diese:Den
5
zugeordnet ist, der Wert, der zurückgegeben wird, durchm["five"]
die eine Referenz auf ein neu erstelltes element. Wennoperator[]
würde nicht einfügen neuer Elemente das konnte nicht funktionieren auf diese Weise.InformationsquelleAutor der Antwort sth
Ich denke, es ist vor allem, weil im Fall von anzeigen (im Gegensatz zu Vektor, zum Beispiel), es ist ziemlich Billig und einfach zu tun-Sie müssen nur ein einzelnes element. Im Fall von Vektor-Sie könnte verlängern den Vektor, um eine neue Tiefgestellt gültig-aber wenn Ihr neue Tiefgestellt ist jenseits dessen, was bereits vorhanden ist, hinzufügen aller Elemente bis zu diesem Punkt kann ziemlich teuer werden. Wenn Sie erweitern einen Vektor, den Sie auch in der Regel geben Sie die Werte der neuen Elemente Hinzugefügt werden (wenn auch oft mit einem Standard-Wert). In diesem Fall gäbe es keine Möglichkeit zu geben Sie die Werte der Elemente in den Raum zwischen dem vorhandenen und dem neuen.
Gibt es auch einen fundamentalen Unterschied, wie eine Karte ist in der Regel verwendet. Mit einem Vektor, normalerweise gibt es eine klare Abgrenzung zwischen den Dingen, die zu einem Vektor, und Dinge, die mit dem arbeiten, was bereits in der vector. Mit einer Karte, ist das viel weniger der Fall -- es ist viel häufiger code, der manipuliert das Element, das es wenn es einer ist, oder fügt ein neues Element, falls es nicht bereits vorhanden ist. Das design von operator[] für jede spiegelt das wider.
InformationsquelleAutor der Antwort Jerry Coffin
Der Unterschied hier ist, dass die Karte speichert den "index", d.h. der Wert in der map gespeichert (in der zugrunde liegenden RB-Baum) ist ein
std::pair
und nicht einfach nur "indiziert" - Wert.Es gibt immer
map::find()
würden Sie sagen, wenn pair mit einem gegebenen Schlüssel existiert.InformationsquelleAutor der Antwort Nikolai Fetissov
Die Antwort ist, weil Sie wollte, eine Umsetzung, die ist bequem und schnell.
Die zugrunde liegende Implementierung ein Vektor ist ein array. Also, wenn es 10 Einträge in dem array, und Sie wollen den Eintrag 5, die T& vector::operator[](5) - Funktion nur die Renditen headptr+5. Wenn Sie Fragen zum Eintrag 5400 gibt es headptr+5400.
Die zugrunde liegende Implementierung einer Karte ist in der Regel ein Baum. Jeder Knoten wird dynamisch zugewiesen, im Gegensatz zu den Vektor, die der standard erfordert zusammenhängend sein. So nodeptr+5 bedeutet gar nichts, und anzeigen["some string"] bedeutet nicht, rootptr+offset("some string").
Wie findet, mit Karten, Vektor hat getAt (), wenn Sie wollen bounds checking. Im Fall von Vektoren, die bounds checking wurde als unnötige Kosten für diejenigen, die nicht wollen, dass es. Im Fall von "maps", die einzige Möglichkeit, nicht zurückzukehren, eine Referenz auf eine exception zu werfen und das wurde auch berücksichtigt, unnötige Kosten für diejenigen, die nicht wollen, dass es.
InformationsquelleAutor der Antwort jmucchiello
Karte.insert(key, item); stellt sicher, dass Schlüssel ist in der Karte aber nicht überschreibt einen bestehenden Wert.
Karte.operator[key] = item; stellt sicher, dass Schlüssel ist in der Karte und überschreibt den vorhandenen Wert mit Element.
Diese beiden Vorgänge sind wichtig genug, um eine einzige Zeile code. Die Designer wahrscheinlich abgeholt, die Bedienung wurde intuitiver für operator[] und erstellt einen Aufruf der Funktion für die anderen.
InformationsquelleAutor der Antwort me.
Überlegen, wie eine input - 3-Blöcke, jeder block 2 Zeilen, erste Zeile ist die Anzahl der Elemente in der zweiten:
Problem: berechnen Sie die Anzahl der zahlen, die vorhanden sind, im zweiten Zeilen aller drei Blöcke. (Für dieses Beispiel für die Eingabe die Ausgabe 3 sein sollte so weit wie 13, 43 und 146 vorhanden sind, die zweiten Zeilen aller drei Blöcke)
Sehen Sie, wie schön ist dieser code:
Gemäß der Norm
operator[]
gibt Referenz auf(*((insert(make_pair(key, T()))).first)).second
. Das ist, warum ich schreiben könnte:und es wird ein element mit Schlüssel
curr
und initialisiert den Wert auf null, wenn der Schlüssel war nicht in der Karte. Und es erhöht den Wert, trotz das element in die Karte oder nicht.Sehen Sie, wie einfach? Es ist schön, nicht wahr? Dies ist ein gutes Beispiel, dass es wirklich bequem.
InformationsquelleAutor der Antwort Narek
Es ist nicht möglich zu vermeiden, die Schaffung eines Objekts, weil der operator[] nicht wissen, wie es zu benutzen.
myMap["apple"] = "green";
oder
char const * cColor = myMyp["apple"];
Schlage ich vor, die map-container hinzufügen sollte, eine Funktion wie
if( ! myMap.exist( "apple"))
throw ...
es ist viel einfacher und besser zu Lesen als
if( myMap.find( "apple") != myMap.end())
throw ...
InformationsquelleAutor der Antwort Clemens