2009-09-25 4 views
70

exemple Contrived, pour le bien de la question:Pourquoi l'opérateur [] n'est-il pas affecté aux cartes STL?

void MyClass::MyFunction(int x) const 
{ 
    std::cout << m_map[x] << std::endl 
} 

Ce ne compilera pas, puisque l'opérateur [] est non-const.

Ceci est regrettable, car la syntaxe [] semble très propre. Au lieu de cela, je dois faire quelque chose comme ceci:

void MyClass::MyFunction(int x) const 
{ 
    MyMap iter = m_map.find(x); 
    std::cout << iter->second << std::endl 
} 

Cela m'a toujours embêté. Pourquoi l'opérateur [] est-il non-const?

+4

Que doit 'opérateur []' rendement en cas l'élément donné n'existe pas? –

+1

@Frerich Raabe: La même chose que la fonction at: throw std :: out_of_range –

Répondre

76

Pour std::map, operator[] insérera la valeur d'index dans le récipient si elle n'existait pas auparavant. C'est un peu inintéressant, mais c'est comme ça.

Puisqu'il doit être autorisé à échouer et insérer une valeur par défaut, l'opérateur ne peut pas être utilisé sur une instance const du conteneur.

http://en.cppreference.com/w/cpp/container/map/operator_at

+1

'std :: set' n'a pas' operator [] '. – avakar

+0

Oops, c'est vrai. Édité. – Alan

+0

C'est la bonne réponse, mais une version const pourrait faire la même chose que le membre "at". C'est jeter un std :: out_of_range ... –

0

Un opérateur d'index doit uniquement être const pour un conteneur en lecture seule (qui n'existe pas réellement en tant que STL).

Les opérateurs d'index ne sont pas seulement utilisés pour regarder des valeurs.

+4

La question est, pourquoi n'a-t-il pas deux versions surchargées - un 'const', un autre non-' const '- comme par exemple. 'std :: vector' fait. –

26

Note pour les nouveaux lecteurs.
La question originale portait sur les conteneurs STL (pas spécifiquement sur la std :: map)

Il convient de noter qu'il existe une version const de l'opérateur [] sur la plupart des conteneurs.
C'est juste que std :: map et std :: set n'ont pas de version const et c'est le résultat de la structure sous-jacente qui les implémente.

De std :: vector

reference  operator[](size_type n) 
const_reference operator[](size_type n) const 

également pour votre deuxième exemple vous devriez vérifier un défaut de trouver l'élément.

void MyClass::MyFunction(int x) const 
{ 
    MyMap iter = m_map.find(x); 
    if (iter != m_map.end()) 
    { 
     std::cout << iter->second << std::endl 
    } 
} 
+0

'std :: set' n'a pas de' operator [] 'du tout. – Everyone

0

Si vous déclarez votre std :: carte variable membre à être mutable

mutable std::map<...> m_map; 

vous pouvez utiliser les fonctions de membres non-const de std :: carte au sein de vos fonctions membres const.

+13

C'est une idée terrible, cependant. – GManNickG

+0

Pourquoi est-ce une idée terrible? –

+6

L'API pour votre classe se trouve si vous faites cela. La fonction prétend que c'est const - ce qui signifie qu'elle ne modifiera aucune variable membre - mais en réalité, elle pourrait modifier le membre de données m_map. – Runcible

3

Puisque l'opérateur [] peut insérer un nouvel élément dans le conteneur, il ne peut pas être une fonction membre const. Notez que la définition de operator [] est extrêmement simple: m [k] est équivalent à (* ((m.insert (type_valeur (k, type_données()))). First)). Second. Strictement parlant, cette fonction de membre est inutile: il existe seulement pour des raisons pratiques

41

Maintenant que avec 11 C++ vous pouvez avoir une version plus propre en utilisant at()

void MyClass::MyFunction(int x) const 
{ 
    std::cout << m_map.at(x) << std::endl; 
} 
+3

Si 'map' a const et non-const' at() 's - pourquoi pas la même chose pour' operator [] '? avec la version const n'insérant rien mais en lançant plutôt? (Ou renvoyer un optionnel, quand std :: optionnel le fait dans la norme) – einpoklum

+0

@einpoklum Le point de const correct est principalement la vérification statique de la compilation. Je préférerais que le compilateur se plaigne plutôt que de lancer une exception car je n'ai pas utilisé les objets const correctement. –