Hallo!
Da muss halt der Nutzer drauf achten!
Im Ernst: C ist eine alte, recht archaische Hochsprache, die genau das tut, was du ihr sagst. Schreiben an eine Position eines Arrays, die größer ist als das Array? Kein Problem. Das Betriebssystem wird das meist mit einem Segmentation Fault quittieren, aber C selbst hat damit kein Problem. C++ ist prinzipiell eine Erweiterung von C, aber auch nicht viel anders.
Natürlich hat sich auch C/C++ über die Jahre weiter entwickelt, aber das grundsätzliche Paradigma, dass der Programmierer wissen muss, was er tut, ist erhalten geblieben.
Java ist da weitaus moderner, es erschlägt dich beispielsweise mit Warnungen. Das tut C/C++ prinzipiell nicht.
Jetzt noch ein paar Dinge:
Der Compiler schaut sich deinen Code an, und wird vieles daran optimieren. Unter anderem wird er feststellen, dass da eine Map mit viel Inhalt direkt im Code steht, und wird im fertigen Programm sozusagen einen vorgefertigten Datenblock anlegen, der diese Daten enthält. Wenn du das Programm ausführst, wird da nicht erst ne Map mit all den Daten gefüllt, sondern sie ist quasi schon da. Das heißt, in deinem Fall müsste eine solche Warnung vom Compiler kommen, nicht vom Programm selbst. (Tut sie aber nicht)
Wenn man sich die Doku zu unordered maps anschaut, gibt es prinzipiell zwei Möglichkeiten, Daten einzufügen. mit []
werden Daten hinzugefügt oder ersetzt, mit .insert()
werden sie nur eingefügt, wenn der Key noch nicht existiert. Dabei wird ein std::pair
zurück gegeben, dessen zweites Element angibt, ob der Wert denn nun eingefügt wurde, oder nicht.
Der unten aufgeführte Code nutzt drei maps. Im ersten Fall so wie bei dir durch Initialisierung gefüllt, im zweiten durch []
, und im dritten durch .insert()
.
Die Ausgabe sieht so aus:
Original
A[3] = Drei
A[2] = Zwei
A[1] = Eins die Erste
Manuelles Insert per []
B[3] = Drei
B[2] = Zwei
B[1] = Eins die Vierte
Manuelles Insert insert()
Eins die Erste -> 1
Zwei -> 1
Drei -> 1
Eins die Zweite -> 0
Eins die Dritte -> 0
Eins die Vierte -> 0
C[3] = Drei
C[2] = Zwei
C[1] = Eins die Erste
Man sieht also, dass []
ersetzt, .insert()
aber nicht, und dabei genau diese Info auch rausgibt. Die Initialisierung hält sich an die .insert()
-Methode.
#include <unordered_map>
#include <string>
#include <iostream>
#include <vector>
using std::unordered_map;
using std::string;
using std::cout;
using std::vector;
int main() {
std::cout << "Original"<< std::endl;
unordered_map<int, string> A {
{ 1, "Eins die Erste" },
{ 2, "Zwei" },
{ 3, "Drei" },
{ 1, "Eins die Zweite" },
{ 1, "Eins die Dritte" },
{ 1, "Eins die Vierte" }
};
for (auto e : A) {
std::cout << "A[" << e.first << "] = " << e.second << std::endl;
}
//##################################################################
std::cout << "\n\nManuelles Insert per []"<< std::endl;
unordered_map<int, string> B;
B[1]="Eins die Erste";
B[2]="Zwei";
B[3]="Drei";
B[1]="Eins die Zweite";
B[1]="Eins die Dritte";
B[1]="Eins die Vierte";
for (auto e : B) {
std::cout << "B[" << e.first << "] = " << e.second << std::endl;
}
//##################################################################
std::cout << "\n\nManuelles Insert insert()"<< std::endl;
unordered_map<int, string> C;
std::cout << "Eins die Erste -> " << C.insert({1, "Eins die Erste"}).second << std::endl;
std::cout << "Zwei -> " << C.insert({2, "Zwei"}).second << std::endl;
std::cout << "Drei -> " << C.insert({3, "Drei"}).second << std::endl;
std::cout << "Eins die Zweite -> " << C.insert({1, "Eins die Zweite"}).second << std::endl;
std::cout << "Eins die Dritte -> " << C.insert({1, "Eins die Dritte"}).second << std::endl;
std::cout << "Eins die Vierte -> " << C.insert({1, "Eins die Vierte"}).second << std::endl;
for (auto e : C) {
std::cout << "C[" << e.first << "] = " << e.second << std::endl;
}
}
Zum Schluss noch das: Du siehst, dass du dich bei einer unordered map noch nicht mal drauf verlassen kannst, dass die Reihenfolge, mit der du sie gefüllt hast, erhalten bleibt. Ist halt unordered. Das heißt, wenn bei deinem Vorwahl-Problem zuerst ein Kiterium geprüft werden muss, und dann erst ein anderes, dann lässt sich das damit nicht umsetzen.
Noch was generelles:
Im ersten Moment scheint es ja, dass eine unordered map eine einfachere Version einer ordered map ist, und dass man dann wohl die nimmt, wenn ordered nicht notwendig ist.
Aber…
Eine ordered map ist wie ein Telefonbuch. Ob ein Name darin auftaucht, lässt sich rasend schnell prüfen, und im gleichen Schritt findet man heraus, wo man einen neuen Eintrag einfügen müsste.
Eine unordered map muss dagegen ALLE Einträge durchgehen, um herauszufinden, ob ein Eintrag bereits existiert.
Das heißt: Beim lesenden Zugriff ist die ordered Map schneller, und beim Einfügen… auch.