web-dev-qa-db-fra.com

L'accès à la carte C ++ élimine les qualificatifs (const)

Le code suivant indique que le passage de la carte en tant que const dans la méthode operator[] Supprime les qualificatifs:

#include <iostream>
#include <map>
#include <string>

using namespace std;

class MapWrapper {
public:
    const int &get_value(const int &key) const {
        return _map[key];
    }

private:
    map<int, int> _map;
};

int main() {
    MapWrapper mw;
    cout << mw.get_value(42) << endl;
    return 0;
}

Est-ce à cause de l'allocation possible qui se produit sur l'accès à la carte? Aucune fonction avec accès à la carte ne peut-elle être déclarée const?

MapWrapper.cpp:10: error: passing ‘const std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >’ as ‘this’ argument of ‘_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = int, _Tp = int, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, int> >]’ discards qualifiers

103
cdleary

Le std::map De operator [] N'est pas déclaré comme const et ne peut pas être dû à son comportement:

T & opérateur [] (const Key & key)

Renvoie une référence à la valeur mappée à une clé équivalente à clé, effectuant l'insertion si cette clé n'existe pas déjà.

Par conséquent, votre fonction ne peut pas être déclarée const et utilisez le operator[] De la carte.

La fonction std::map De find() vous permet de rechercher une clé sans modifier la carte.

find() renvoie un iterator ou const_iterator À un std::pair contenant à la fois la clé (.first) Et la valeur (.second).

En C++ 11, vous pouvez également utiliser at() pour std::map. Si l'élément n'existe pas, la fonction lève une exception std::out_of_range, Contrairement à operator [].

143
luke

Puisque operator[] n'a pas de surcharge qualifiée const, elle ne peut pas être utilisée en toute sécurité dans une fonction qualifiée const. Cela est probablement dû au fait que la surcharge actuelle a été créée dans le but de renvoyer et de définir des valeurs clés.

Au lieu de cela, vous pouvez utiliser:

VALUE = map.find(KEY)->second;

ou, en C++ 11, vous pouvez utiliser l'opérateur at() :

VALUE = map.at(KEY);
10
Richard

Vous ne pouvez pas utiliser operator[] sur une carte qui est const car cette méthode n'est pas const car elle vous permet de modifier la carte (vous pouvez affecter à _map[key]). Essayez plutôt d'utiliser la méthode find.

10
nlativy

Certaines versions plus récentes des en-têtes GCC (4.1 et 4.2 sur ma machine) ont des fonctions membres non standard map :: at () qui sont déclarées const et lancent std :: out_of_range si la clé n'est pas dans la carte.

const mapped_type& at(const key_type& __k) const

D'après une référence dans le commentaire de la fonction, il semble que cela a été suggéré comme une nouvelle fonction membre dans la bibliothèque standard.

7
Nathan Kitchen

Tout d'abord, vous ne devez pas utiliser de symboles commençant par _ car ils sont réservés au rédacteur du compilateur/implémentation du langage. Il serait très facile pour _map d'être une erreur de syntaxe sur le compilateur de quelqu'un, et vous n'auriez d'autre responsable que vous-même.

Si vous souhaitez utiliser un trait de soulignement, mettez-le à la fin, pas au début. Vous avez probablement fait cette erreur car vous avez vu du code Microsoft le faire. N'oubliez pas, ils écrivent leur propre compilateur, afin qu'ils puissent s'en tirer. Même ainsi, c'est une mauvaise idée.

l'opérateur [] ne renvoie pas seulement une référence, il crée en fait l'entrée dans la carte. Donc, vous n'obtenez pas seulement un mappage, s'il n'y en a pas, vous en créez un. Ce n'est pas ce que tu voulais.

0
Dov