2012-11-13 11 views
10

Warum darf ich ein Objekt nicht von einer konstanten unordered_map lesen?Leseobjekt von const unordered_map

const unordered_map<int, int> z; 
int val = z[5]; // compile error 

Der Fehler unter Klirren ist die folgende:

error: no viable overloaded operator[] for type 'const 
     unordered_map<int, int>' 
         int val = z[5]; 

Anbetracht dessen, dass der entsprechende Code ein const vector funktioniert Ich bin ein wenig verwirrt, warum wir dieses Verhalten mit zu bekommen.

Antwort

16

Der Ausdruck z[5] ruft eine nicht konstante Elementfunktion der Map auf.

Dies ist, weil eine Karte operator[] ein neues Element einfügen wird, wenn der Schlüssel nicht gefunden wird, also offensichtlich muss es nicht-const sein.

Für eine vector nichts von operator[] eingefügt wird, muss das Element bereits existieren (oder Sie erhalten undefiniertes Verhalten, so würde der entsprechende Code auf das 6. Element eines leeren Vektors zugreifen, was nicht in Ordnung ist!).

Um einen Schlüssel-Lookup, ohne es zu verwenden, fügt hinzu:

int val = 0; 
auto it = z.find(5); 
if (it != z.end()) 
    val = it->second; 
+7

Um ein wenig weniger wortreich zu sein, können Sie auch 'int val = z.at (5);' verwenden - In diesem Fall erhalten Sie eine 'std :: out_of_range' Ausnahme, wenn der Schlüssel nicht ist in der Karte. Natürlich ist es nicht weniger ausführlich, wenn Sie es in einem Try-Catch-Block umgeben. –

+0

Ah ja, ich habe dieses Verhalten der Karte vergessen - ich finde es ziemlich überraschend, dass das Nachschlagen eines Schlüssels den Standardwert in die Karte einfügen kann, aber das erklärt, obwohl es keine konstante Elementfunktion ist. Wird es in 2 Minuten akzeptieren :) (und ja @Benjamin 'at' ist sowieso die beste Wahl für mich im Code, denn es wäre ein schwerer Fehler, den Wert zu diesem Zeitpunkt nicht zu finden). – Voo

+0

@Voo: Es mag auf den ersten Blick überraschend sein, aber es wird sofort klar, dass sonst nichts wirklich Sinn macht. –

1

Wie Jonathan bereits gesagt, die operator[] Methode ist nicht-const da es nicht gefunden hinzufügen möchte ist ein Standardwert, wenn das Element nachgeschlagen.

Auf der anderen und, wie von Benjamin in einem Kommentar hervorgehoben, ist die at()-Methode auch für const verfügbar.

const unordered_map<int, int> z; 
int val = z.at(5); // Success! 

Der Nachteil ist, dass, wenn der Wert nachgeschlagen ist nicht in der Karte, eine std::out_of_range Ausnahme angehoben wird, so hat es geschafft werden.