Dinge assoziieren

Viele Programmiersprachen bieten assoziative Container: Container, deren Index aus beliebigen Objekten bestehen kann, statt nur auf Integer beschränkt zu sein. C++ ist da keine Ausnahme. Genaugenommen bietet es mehrere verschiedene Varianten für unterschiedliche Ansätze. Eine davon: std::map.

Video

Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>
#include <map>
 
int main()
{
  std::map<std::string, std::string> capital
  {
    { "Deutschland", "Berlin" },
    { "Polen", "Warschau" },
    { "Schweden", "Stockholm" },
    { "Italien", "Rom" }
  };
 
  std::cout << capital["Deutschland"] << std::endl;
   
  capital["Frankreich"] = "Paris";
  std::cout << capital.at("Frankreich") << std::endl;
   
  std::cout << capital["Norwegen"] << std::endl;
  std::cout << capital.at("Finnland") << std::endl;
}

Erklärung

Der Quelltext ist fast selbsterklärend: wir möchten (das Standardbeispiel…) zu einem Land seine Hauptstadt speichern und ggf. abrufen können. Dafür bietet sich ein assoziativer Container an: als Index wird der Name des Landes verwendet, als Wert der Name der Hauptstadt. Wie alles in C++ müssen natürlich Schlüssel und Wert streng typisisert sein. std::map ist daher ein Template, welches mindestens zwei Parameter nimmt: den Schlüsseltyp (in unserem Fall std::string) und den Werttyp (in unserem Fall ebenfalls std::string). Mittels einer Initialisierungsliste wird unsere capital-Map schon mal vorbelegt: paarweise werden die Abbildungen vorbelegt.

Das Auslesen der Map ist dann analog zum Indexzugriff in einem Array: operator[] wird mit dem Schlüssel aufgerufen und liefert den dahinter stehenden Wert zurück. Der Operator kann ebenso genutzt werden, um etwas in die Map einzufügen: er liefert eine schreibbare Referenz auf das Objekt mit dem betreffenden Schlüssel. Hier liegt auch schon eine der Stolperfallen von std::map begraben: wenn ein Schlüssel nicht vorhanden ist, dann wird er eingefügt, um die schreibbare Referenz zurückliefern zu können. Um das zu vermeiden, gibt es eine zweite Variante für den Indexzugriff, die Java-Programmierern etwas bekannter vorkommen sollte: die Methode at() nimmt ebenso einen Schlüssel und liefert dessen Wert. Im Gegensatz zu operator[] wird allerdings bei fehlendem Schlüssel der Wert nicht angelegt, sondern eine Exception geworfen. Deswegen verhalten sich die Zeilen 20 und 21 unterschiedlich: 20 gibt einen leeren String aus (der mittels Default-Konstruktor neu angelegte Wert für den Schlüssel “Norwegen”), 21 wirft eine std::out_of_range-Exception um anzuzeigen, dass der Wert “Finnland” nicht in der Map vorhanden ist.