web-dev-qa-db-fra.com

Quelle est la différence entre la clé const et non const?

Quelle est la différence entre les deux lignes suivantes?

map<int, float> map_data;
map<const int, float> map_data;
74
NullPoiиteя
  • int et const int sont deux types distincts.

  • std::map<int, float> et std::map<const int, float> sont de même types différents.

La différence entre std::map<const int, float> et std::map<int, float> est, dans une certaine mesure, analogue à la différence entre, disons, std::map<int, float> et std::map<std::string, float>; vous obtenez un nouveau type de carte pour chacun.

Dans le cas non -const, le type de clé interne est toujours non -constint:

std::map<const int, float>::key_type       => const int
std::map<int, float>::key_type             => int

Cependant, les clés de mappage sont sémantiquement immuables, et toutes les opérations de mappage qui permettent un accès direct aux clés (par exemple, déréférencer les itérateurs, ce qui donne value_type) constifie le key_type:

std::map<const int, float>::value_type => std::pair<const int, float>
std::map<int, float>::value_type       => std::pair<const int, float>

Ainsi, la différence mai vous sera largement invisible de toutes les manières qui comptent, si votre implémentation le permet.

Ce n'est pas toujours le cas, cependant: la norme officiellement requiert votre type de clé pour être copiable et mobile, et certaines implémentations réutilisent les nœuds de carte ; sous ces implémentations, tenter d'utiliser une clé const ne fonctionnera tout simplement pas.

58

clé est déjà const, il est donc redondant d'écrire const dans ce cas. Une fois qu'un élément est entré, son key ne peut pas être modifié.


Modifier :

Comme mentionné dans les commentaires, il y a différence entre les deux lignes. Par exemple, si vous écrivez une fonction qui accepte map<const int, int>, vous ne pouvez pas y passer map<int, int> car ils sont différents types.

Mais notez que bien qu'ils soient de types différents, ils se comportent de la même manière puisque la clé dans une carte est de toute façon un const ...

Donc en conclusion .. La seule différence est qu'ils sont de deux types différents, vous ne devriez pas vous soucier d'autre chose.

36
Maroun

La différence est que la deuxième variante définira le type de clé pour la carte comme const int. Du point de vue de la "modifiabilité", cela est redondant, car la carte stocke déjà ses clés en tant qu'objets const.

Cependant, cela peut également entraîner des différences inattendues et non évidentes dans le comportement de ces deux cartes. En C++, une spécialisation de modèle écrite pour le type T est différente de la spécialisation écrite pour le type const T. Cela signifie que les deux versions ci-dessus de la carte pourraient finir par utiliser différentes spécialisations de divers modèles de "satellites" qui dépendent du type de clé. Un exemple est le prédicat du comparateur clé. Le premier utilisera std::less<int> tandis que le second utilisera std::less<const int>. En exploitant cette différence, vous pouvez facilement créer ces cartes pour trier leurs éléments dans un ordre différent.

De tels problèmes sont plus évidents avec les nouveaux conteneurs C++ 11 comme std::unordered_map. std::unordered_map<const int, int> ne compilera même pas, car il tentera d'utiliser un std::hash<const int> spécialisation pour le hachage des clés. Une telle spécialisation n'existe pas dans la bibliothèque standard.

8
AnT

const ne peut pas être modifié une fois défini. Et oui, selon les documents et autres réponses, vous devez vous rappeler que key est déjà const.

Lien: http://www.cplusplus.com/reference/map/map/ Lien: http://en.cppreference.com/w/cpp/container/map =

3
Shumail

Bien que le comportement de votre application soit généralement le même, cela fait une différence pour certains compilateurs que vous pourriez utiliser. L'exemple plus spécifique de ce qui m'a amené à cette page en premier lieu:

Spécification explicite d'une carte comme map<const key, value> se construit avec succès avec la boîte à outils gnu;

Cependant, il plante une version Studio12 Solaris x86.


map<key, value> s'appuie avec succès sur les deux. Le comportement de l'application est inchangé.

2
blgt

Les touches const peuvent être utiles si les touches sont des pointeurs. L'utilisation de clés const ne vous permettra pas de modifier l'objet pointé lors de l'accès aux clés, considérez ceci:

#include <map>
#include <string>

int glob = 10;

int main() {
    std::map<const int*, std::string> constKeyMap { { &glob, "foo"} };
    std::map<int*, std::string> keyMap { { &glob, "bar" } };

    for(const auto& kv : keyMap) { *(kv.first) = 20; }; // glob = 20
    for(const auto& kv : constKeyMap) { *(kv.first) = 20; }; // COMPILE ERROR

    return 0;
}
0
SiimKallas