2012-11-13 27 views
10

Perché non mi è permesso di leggere un oggetto da un unordered_map costante?lettura da unordered_map const

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

L'errore sotto clang è il seguente:

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

Considerando che il codice equivalente utilizzando un const vector funziona bene io sono un po 'confuso perché riusciamo ad ottenere questo comportamento.

risposta

16

L'espressione z[5] chiama una funzione membro non const della mappa.

Questo perché un operator[] di una mappa inserirà un nuovo elemento se la chiave non viene trovata, quindi ovviamente deve essere non-const.

Per un vector non viene inserito nulla da operator[], l'elemento deve esistere già (oppure si ottiene un comportamento non definito, quindi il codice equivalente accederà al sesto elemento di un vettore vuoto, che non è corretto!).

di ricercare una chiave senza l'aggiunta di esso uso:

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

Per essere un po 'meno prolisso, puoi anche usare 'int val = z.at (5);' - In tal caso, otterrai un'eccezione 'std :: out_of_range' se la chiave non è nella mappa Naturalmente, non è meno dettagliato se lo si circonda in un blocco try-catch. –

+0

Ah sì, ho dimenticato questo comportamento della mappa - Trovo abbastanza sorprendente che la ricerca di una chiave possa inserire il valore predefinito nella mappa, ma ciò spiega mentre non è una funzione membro const. Lo accetterò in 2 minuti :) (e sì @Benjamin 'at' è comunque la scelta migliore per me nel codice, perché non trovando il valore a questo punto sarebbe un errore grave). – Voo

+0

@Voo: Può sembrare sorprendente a prima vista, ma diventa immediatamente chiaro che nient'altro ha davvero senso. –

1

Come già detto Jonathan, il metodo operator[] è non-const perché potrebbe aggiungere un valore predefinito quando la voce alzò gli occhi non è stato trovato.

Dall'altro e, come evidenziato da Benjamin in un commento, il metodo at() è disponibile anche per const.

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

Il rovescio della medaglia è che quando il valore alzò gli occhi, non è nella mappa, un'eccezione std::out_of_range è sollevata, quindi deve essere gestito.