2011-11-29 11 views
6

Sto leggendo:Perché solo le mappe non costanti forniscono il richiamo diretto di elementi associativi di tipo array?

La libreria standard C++: Un tutorial e una di riferimento da Nicolai M. Jossuttis

è il mio go-to prenotare quando ho intenzione di utilizzare alcuni meccanismi STL in qualsiasi modo significativo. Ad ogni modo, mi ha subito rileggendo i capitoli sulla std :: map e relativi algoritmi e ho notato una frase che non avevo pensato prima:

mappe

non costante forniscono un operatore di indicizzazione per l'accesso elemento diretto. Tuttavia, l'indice dell'operatore di pedice non è la posizione integrale dell'elemento. ... ecc.

Perché è possibile utilizzare solo le mappe non costanti in un array associativo? Sembra che sarebbe abbastanza semplice fornire una semantica di sola lettura in questo caso. Suppongo che le eccezioni sarebbero possibili se provaste a recuperare un elemento con una chiave che non esistesse (seno non è possibile aggiungere una nuova chiave/valore alla mappa se è costante).

Mi piacerebbe capire il ragionamento dietro questo se qualcuno può far luce :) grazie!

+0

Come vi aspettate 'mappare [ "foo"]' di lavorare su un 'un'istanza const' di' std :: map' se non v'è alcun elemento corrispondente? Non può creare da quando il 'map' è const e gettando un'expection essere diverso dal comportamento non-const che potrebbe essere pericoloso. – ereOn

risposta

11

Perché può solo mappe non costanti essere utilizzati in un array associativo come modo?

Perché questi operatori restituiscono un riferimento all'oggetto associato a una chiave particolare. Se il contenitore non contiene già un oggetto di questo tipo, operator[] inserisce l'oggetto predefinito. Ora, se il contenitore è costante, non è possibile inserire alcun oggetto e non è possibile restituire un riferimento a oggetti non esistenti, per cui questi operatori sono disponibili solo per contenitori non costanti.

Lanciare un'eccezione in tal caso è possibile, ovviamente, ma non è il modo migliore per affrontare casi piuttosto generici quando l'oggetto per una determinata chiave non esiste. Fondamentalmente, le eccezioni sono estremamente costose e sono per situazioni eccezionali, e quella sopra non lo è, quindi non ne vale la pena.

Il modo migliore sarebbe restituire un iteratore, ma l'utente dovrebbe verificare se non è "fine", il che renderà il caso d'uso simile a find(), quindi inutile. È anche possibile restituire iteratori o puntatori per contenitori a sola costante, ma ciò interrompe un po 'la semantica ed è fonte di confusione.

1

Il [] -operator muta il contenitore: se la chiave non esiste, verrà creata:

return m[1];  // **creates** m[1] if it doesn't exist 

return *m.find(1) // UB if m[1] doesn't exist (dereferencing m.end()) 

Inoltre, [] restituisce sempre un riferimento non costante, in modo da poter dire m[1] = 2;. D'altra parte, find() restituisce un iteratore la cui costanza è quello della mappa stessa:

map_t m; 
*m.find(1) = 2; // Only OK if m[1] exists 
// *const_cast<map_t const &>(m).find(1) = 2; // error 
1

[] l'operatore modifica la mappa, se la chiave non esiste.

Se la chiave non esiste, la mappa crea una nuova voce con la chiave e un valore predefinito per il valore associato e restituisce il suo riferimento.Perché ciò accada, operator[] deve essere funzione non-const, che significa che non può operare su const istanza di std::map.

8

In C++ 11 è possibile utilizzare at() per ottenere che il comportamento "ottenere il valore, altrimenti eccezione tiro mappato". Sovraccarico operator[] fare due cose diverse (cioè o inserire nuovo paio o laterale) a seconda se una mappa è costante sarebbe troppo confuso e soggetto ad errori.

Problemi correlati