Accès aux éléments de carte const C ++

101

J'ai essayé d'utiliser l'opérateur [] pour accéder à l'élément dans une carte const C ++, mais cette méthode a échoué. J'ai aussi essayé d'utiliser "at ()" pour faire la même chose. Cela a fonctionné cette fois. Cependant, je n'ai trouvé aucune référence sur l'utilisation de "at ()" pour accéder à l'élément dans une carte const C ++. "At ()" est-il une fonction nouvellement ajoutée dans la carte C ++? Où puis-je trouver plus d'informations à ce sujet? Merci beaucoup!

Un exemple pourrait être le suivant:

#include <iostream>
#include <map>

using namespace std;

int main()
{
        map<int, char> A;
        A[1] = 'b';
        A[3] = 'c';

        const map<int, char> B = A;

        cout << B.at(3) << endl; // it works
        cout << B[3] << endl;  // it does not work

}

Pour utiliser "B [3]", il a renvoyé les erreurs suivantes lors de la compilation:

t01.cpp: 14: erreur: passer 'const std :: map, std :: allocator>>' comme 'this' argument de '_Tp & std :: map <_Key, _Tp, _Compare, _Alloc> :: operator [] ( const _Key &) [with _Key = int, _Tp = char, _Compare = std :: less, _Alloc = std :: allocator>] 'ignore les qualificatifs

Le compilateur utilisé est g ++ 4.2.1

glace
la source

Réponses:

124

at()est une nouvelle méthode pour std::mapen C ++ 11.

Plutôt que d'insérer un nouvel élément construit par défaut comme operator[]si un élément avec la clé donnée n'existe pas, il lève une std::out_of_rangeexception. (Ceci est similaire au comportement de at()for dequeet vector.)

En raison de ce comportement, il est logique qu'il y ait une constsurcharge de at(), contrairement à operator[]ce qui a toujours le potentiel de changer la carte.

CB Bailey
la source
Est-il possible que "at" renvoie une valeur par défaut au lieu de lever une exception?
user1202136
J'utilise at()avec dans VS2013 sur un projet configuré pour utiliser la boîte à outils VS2010. Je pensais que cela signifiait que je n'utilisais pas C ++ 11 ... Mais pourtant, il compile ... ??
thomthom
1
J'ai juste besoin de dire que cela n'a pas de sens d'omettre l'opérateur const [], qui pourrait également lancer une exception pour un élément non mappé au lieu de changer la carte.
Spencer
@Spencer Il serait surprenant que les surcharges const et non const de l'opérateur [] aient des effets différents. Normalement, nous nous attendons à ce que si certains objets ou références non const dans un programme deviennent const, le programme continuera à se comporter de la même manière, tant qu'il se compile. Autoriser uniquement la surcharge non-const à lever des exceptions peut entraîner des bogues qui ne sont pas interceptés avant l'exécution.
Brian
@Brian Vouliez-vous dire "Autoriser uniquement la surcharge const à lever des exceptions"?
Spencer
33

Si un élément n'existe pas dans a map, le operator []ajoutera - ce qui ne peut évidemment pas fonctionner dans une constcarte, donc C ++ ne définit pas de constversion de l'opérateur. Ceci est un bel exemple du vérificateur de type du compilateur empêchant une erreur d'exécution potentielle.

Dans votre cas, vous devez utiliser à la findplace qui ne renverra un (itérateur à l'élément) que s'il existe, il ne modifiera jamais le map. Si un élément n'existe pas, il renvoie un itérateur sur celui de la carte end().

atn'existe pas et ne devrait même pas compiler. Peut-être s'agit-il d'une «extension de compilateur» (=un bug nouveau dans C ++ 0x).

Konrad Rudolph
la source
Le standard C ++ interdit-il à l'implémentation de définir des fonctions membres non standard supplémentaires dans les classes de bibliothèque?
Tim Martin
@Tim Je crois que l'interface est fixe, oui.
Konrad Rudolph
4

L'opérateur [] créera une nouvelle entrée dans la carte si la clé donnée n'existe pas. Cela peut donc changer la carte.

Voir ce lien .

vidstige
la source