IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

Problème avec map


Sujet :

SL & STL C++

  1. #1
    Nouveau membre du Club
    Inscrit en
    Novembre 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 55
    Points : 32
    Points
    32
    Par défaut Problème avec map
    Bonjour


    Au code suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    std::map<char ,int> bonjour; bonjour["titi"] = 2;


    j'ai à la compil le résultat suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    c:\program files\microsoft visual studio\vc98\include\xtree(200) : warning C4786: '?rbegin@?$_Tree@VCString@@U?$pair@$$CBVCString@@H@std@@U_Kfn@?$map@VCString@@HU?$less@VCString@@@std@@V?$allocator@H@3@@3@U?$less@VCString@@@3@V?$allocator@H@3@@std@@
    QAE?AV?$reverse_bidirectional_iterator@Viterator@?$_Tree@VCString@@U?$pair@$$CBVCString@@H@std@@U_Kfn@?$map@VCString@@HU?$less@VCString@@@std@@V?$allocator@H@3@@3@U?$less@VCString@@@3@V?$allocator@H@3@@std@@U?$pair@$$CBVCString@@H@3@AAU43@PAU43@H@2@
    XZ' : identifier was truncated to '255' characters in the browser information
            c:\program files\microsoft visual studio\vc98\include\map(46) : see reference to class template instantiation 'std::_Tree<class CString,struct std::pair<class CString const ,int>,struct std::map<class CString,int,struct std::less<class CStri
    ng>,class std::allocator<int> >::_Kfn,struct std::less<class CString>,class std::allocator<int> >' being compiled
            E:\Projets\DemoCityRama\Services.cpp(21) : see reference to class template instantiation 'std::map<class CString,int,struct std::less<class CString>,class std::allocator<int> >' being compiled
    c:\program files\microsoft visual studio\vc98\include\xtree(202) : warning C4786: 
     
    ....
    QQu'un aurait il une idée?
    Merci

  2. #2
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Oula le message de VC fait peur, pas très logique tout ça.
    L'erreur c'est que tu tentes de convertir un const char* en char... forcément ça péte.
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Tu prends déjà un bon départ en tentant d'utiliser la STL pour ta collection...

    Pourquoi n'irais tu pas "un peu plus loin" en utilisant... la classe std::string pour représenter ta chaine de caractères

    En effet, il y a le problème que tu déclare la clé comme étant un... char, c'est à dire un... caractère unique.

    Or, si je compte bien, "titi" est composé de... 4 caractères significatifs (5 si on compte le '\0' terminal), et ca, ca s'appelle un tableau de caractères, et, dans le meilleur des cas, on le déclare sous la forme... d'un pointeur de type char

    Mais le fait de déclarer ta map sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<char *, int> bonjour;
    ne suffirait, malheureusement, pas à résoudre ton problème...

    En effet, un tableau de caractères dont le dernier caractère significatif est suivi par un '\0' représente... une chaine de caractère dite "C style", mais il n'en demeure pas moins qu'un char *, c'est un pointeur, et qu'un pointeur, ce n'est jamais... qu'une variable numérique non signée représentant... l'adresse à laquelle on trouvera l' "objet" dont le type est donné (ici, l'objet est... un caractère).

    Or, c'est la valeur de l'adresse qui serait comparée si tu utilisait un char * comme clé pour ta map et ca, ca risquerait de provoquer une situation assez embêtante:

    Il n'est pas du tout exclu que deux chaines de caractères identiques ( "titi", par exemple) se trouvent... en deux adresses mémoire différentes ce qui fait qu'elles seraient considérées comme... différentes, alors qu'elle devraient... être considérées comme équivalentes

    C'est pour cette raison qu'en C, lorsqu'il est question de comparer deux chaines de caractères, il faut avoir recours à ... la fonction strcmp.

    Et nous avons un autre problème propre à l'utilisation de la map: Il n'est pas possible de demander à la map d'utiliser directement la fonction strcmp comme comparateur, car le système permettant de trier les tris est basé sur l'opérateur < (ou sur le prédicat less).

    Et comme si, effectivement, l'opérateur < fonctionne pour un pointeur, c'est l'adresse qu'il contient qui est comparée, c'est à dire que, avec un peu de mal chance, la chaine de caractère "zozo" se trouvera à une adresse inférieure que la chaine de caractère "titi", et que, du coup, la map considérera que "zozo" est... plus petit que titi...

    Du coups, les éléments ont de grandes chances de ne pas être correctement triés dans la std::map...

    Il faut avouer que c'est réellement dommage, non

    Et je ne te ferai pas l'affront de te rappeler tous les autres problèmes liés à l'utilisation des chaines de caractères C style du point de vue de la gestion dynamique de la mémoire

    C'est donc dans ce contexte que la classe std::string intervient.

    D'abord, il faut savoir que cette classe dispose de de l'opérateur < qui permet, effectivement, de savoir si une chaine est plus petite ou plus grande qu'une autre. (d'ailleurs, elle dispose également de l'opérateur de comparaison == et des opérateurs + et += qui servent dans un contexte de concaténation )

    De plus, cette classe gère automatiquement l'espace mémoire dont elle a besoin, ce qui nous permet de ne plus nous en inquiéter

    Enfin, elle est pleinement compatible avec des char const * dans le sens où elle dispose d'un constructeur prenant un tel pointeur en argument ainsi que d'une fonction c_str() permettant, en cas de besoin, de récupérer un char const *.

    Et je ne te parle pas des autres fonctions membres dont elle est affublée, parce que la liste est vraiment longue, mais sache qu'elle permet énormément de choses

    Bref, tu l'auras surement compris en me lisant: il est vraiment préférable d'utiliser la classe std::string chaque fois qu'il te faut gérer des chaines de caractères plutôt que d'utiliser les chaines de caractères C style

    Au final, tous tes problèmes trouveraient une solution, et tu t'en éviterais sans doute beaucoup d'autres en déclarant ta std::map sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::map<std::string, int> bonjour;
    Cependant, je ne peux me résoudre à terminer cette (déjà longue) intervention sans te prodiguer un dernier conseil:

    La comparaison de chaines de caractères prend *énormément* de temps par rapport à la comparaison de valeurs numériques.

    En effet, elle nécessite de comparer un à un les différents caractères de la "première" chaine de caractères avec... le caractère occupant la position correspondante de la "deuxième" chaine de caractères.

    Sur de "petites" chaines de caractères, et, au vu de la puissances des ordianteurs actuels, il est possible que cela n'impacte pas *trop* sur les performances, mais, si les chaines de caractères deviennent importantes et qu'il y en a beaucoup à comparer, l'utilisation d'une chaine de caractères comme clé de tri est *réellement* de nature à "plomber" les performances de la std::map.

    Si les performances sont importantes pour ton projet, il est *peut-être* intéressant d'envisager l'utilisation d'une autre sorte de clé de tri .
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  4. #4
    Nouveau membre du Club
    Inscrit en
    Novembre 2002
    Messages
    55
    Détails du profil
    Informations forums :
    Inscription : Novembre 2002
    Messages : 55
    Points : 32
    Points
    32
    Par défaut
    Déjà merci pour ces explications très intéressantes...

    Mais tjrs le meme pb, à la compile de ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    	std::map <std::string, int> bonjour;
    	bonjour["cou"] = 2;
    j'obtiens les warnings suivantes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    c:\program files\microsoft visual studio\vc98\include\map(27) : warning C4786: '??R_Kfn@?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@H@2@@s
    td@@QBEABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@2@ABU?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@2@@Z' : identifier was truncated to '255' characters in the browser information
            E:\Projets\DemoCityRama\Services.cpp(25) : see reference to class template instantiation 'std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,stru
    ct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >' being compiled
    c:\program files\microsoft visual studio\vc98\include\map(36) : warning C4786: '??Rvalue_compare@?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocat
    or@H@2@@std@@QBE_NABU?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@2@0@Z' : identifier was truncated to '255' characters in the browser information
            E:\Projets\DemoCityRama\Services.cpp(25) : see reference to class template instantiation 'std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,stru
    ct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >' being compiled
    c:\program files\microsoft visual studio\vc98\include\map(38) : warning C4786: '??0value_compare@?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocat
    or@H@2@@std@@QAE@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@@Z' : identifier was truncated to '255' characters in the browser information
            E:\Projets\DemoCityRama\Services.cpp(25) : see reference to class template instantiation 'std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,stru
    ct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >' being compiled
    c:\program files\microsoft visual studio\vc98\include\map(45) : warning C4786: '?$_Tree@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@2@U_Kfn@?$map@V?$basic_
    string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@H@2@@2@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@H@2@' : identifi
    er was truncated to '255' characters in the browser information
            E:\Projets\DemoCityRama\Services.cpp(25) : see reference to class template instantiation 'std::map<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >,int,struct std::less<class std::basic_string<char,stru
    ct std::char_traits<char>,class std::allocator<char> > >,class std::allocator<int> >' being compiled
    c:\program files\microsoft visual studio\vc98\include\xtree(22) : warning C4786: '?$_Tree@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@H@2@U_Kfn@?$map@V?$basi
    c_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@HU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@H@2@@2@U?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@H@2@' : identi
    fier was truncated to '255' characters in the browser information
    ....
    avec les erreurs suivantes
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    c:\program files\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::multimap<_K,_Ty,_Pr,_A> &,const class std::multimap<_K,_Ty,_Pr,_A> &)' : could not deduce template argument for 'const
     class std::multimap<_K,_Ty,_Pr,_A> &' from 'const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >'
            c:\program files\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::opera
    tor ()(const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &) const'
    c:\program files\microsoft visual studio\vc98\include\functional(86) : error C2784: 'bool __cdecl std::operator <(const class std::map<_K,_Ty,_Pr,_A> &,const class std::map<_K,_Ty,_Pr,_A> &)' : could not deduce template argument for 'const class std
    ::map<_K,_Ty,_Pr,_A> &' from 'const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >'
            c:\program files\microsoft visual studio\vc98\include\functional(86) : while compiling class-template member function 'bool __thiscall std::less<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >::opera
    tor ()(const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &,const class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > &) const'
    c:\program files\microsoft visual studio\vc98\include\functional(86) : error C2784:...
    Je n'ai pas précisé que je travaillais sur une appli MFC. Ca peut avoir une influence?

    Merci

  5. #5
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Je ne dispose pas de visual studio pour l'instant, mais, essaye peut être de forcer la création d'une chaine de caractères sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    bonjour[string("toto")]=2;
    car, avec Gcc, il n'y a aucun problème (par contre, il me semble que le problème a déjà été abordé sur le forum...)

    Ceci dit, mon avis personnel est que, quelque part, l'usage de l'opérateur [] est assez malheureux en ce qui concerne les std::map, ne serait-ce parce qu'il a la double sémantique de recherche et d'insertion d'un élément, l'insertion s'effuant "automatiquement" si l'élément recherché n'est pas présent.

    Pour cette raison, je préfère avoir recours aux fonction insert et find:
    bonjour.insert(std::make_pair("titi",2));
    cout<<bonjour.find("titi")->second;
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Bonjour,
    Quelle version de visual utilises-tu ?

  7. #7
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Quand au warning, tu peux l'ignorer complètement. Il précise juste que vu la longueur de l'identifiant généré, le linker pourrait avoir du mal à y retrouver ses petits - en pratique, ce n'est que très très très rarement le cas (je ne l'ai jamais rencontré, malgré des années de MFC+STL)

    En fait, je te suggère de rajouter une ligne #pragma warning(disable:4786) (ou approchant ; je ne me rappelle plus exactement) dans ton fichier stdafx.h, avant toute inclusion de fichier.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  8. #8
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2006
    Messages
    780
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2006
    Messages : 780
    Points : 1 176
    Points
    1 176
    Par défaut
    Avec visual C++ 2010 ça marche, et j'ai souvent utilisé ça aussi avec GCC.

    Ca ne me gène pas vraiment d'utiliser [] pour une insertion, c'est juste pour la récupération où c'est ambigü.

  9. #9
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par nikko34 Voir le message
    Avec visual C++ 2010 ça marche, et j'ai souvent utilisé ça aussi avec GCC.

    Ca ne me gène pas vraiment d'utiliser [] pour une insertion, c'est juste pour la récupération où c'est ambigü.
    C'est bien à cause de cette ambigüité que je regrette sa présence pour les std::map...

    un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    if(lamap["zutEtFlute"]==3)
        /* quelque chose à faire */
    aura comme résultat... de créer un élément dont la clé est "ZutEtFlute" s'il n'en existe pas et dont la valeur sera construite par défaut.

    C'est, quelque part, assez embêtant, non
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  10. #10
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Ceci dit, mon avis personnel est que, quelque part, l'usage de l'opérateur [] est assez malheureux en ce qui concerne les std::map, ne serait-ce parce qu'il a la double sémantique de recherche et d'insertion d'un élément, l'insertion s'effuant "automatiquement" si l'élément recherché n'est pas présent.

    Pour cette raison, je préfère avoir recours aux fonction insert et find:
    bonjour.insert(std::make_pair("titi",2));
    cout<<bonjour.find("titi")->second;
    Si le but est d'insérer d'abord, et de rechercher ensuite (et éventuellement de modifier), il ne faut pas prendre une map, mais un vector trié, ca ira toujours plus vite.

    L'intérêt d'une map, à mon avis, c'est justement cette idée de pouvoir "soit créer soit modifier" un élément. Ca sert quand insertions, recherches et modifications d'éléments se font en ordre dispersé. Et dans ce cas, avoir une même fonction qui recherche, et, le cas échéant, modifie ou crée, c'est plus efficace (sinon, on fait le travail en double).

    Maintenant, plus j'utilise la STL, moins j'utilise les map (et jamais les multimap). En fait, leur principale utilité c'est dans des prototypes, parce que c'est facile à écrire. Dans du code sérieux, on finit presque toujours avec des vector.

    Francois

  11. #11
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par fcharton Voir le message
    Si le but est d'insérer d'abord, et de rechercher ensuite (et éventuellement de modifier), il ne faut pas prendre une map, mais un vector trié, ca ira toujours plus vite.
    Sauf votre respect, l'insertion dans une liste triée est un algorithme en O(N), tandis que l'insertion dans une map, basée sur un RB-tree, se fait en O(log2(N)), donc l'insertion dans la map sera nécessairement plus rapide que l'insertion dans la liste dès que N aura dépassé un treshold relativement faible.

    Idem pour les recherches.

    Citation Envoyé par fcharton Voir le message
    Maintenant, plus j'utilise la STL, moins j'utilise les map (et jamais les multimap). En fait, leur principale utilité c'est dans des prototypes, parce que c'est facile à écrire. Dans du code sérieux, on finit presque toujours avec des vector.

    Francois
    Sauf votre respect (hein ? deux fois ? ), std::map<> et std::vector<> rendent des services qui sont très différents. On utilise les maps pour associer une instance à une clef, et un vecteur est utilisé pour stocker une liste d'instances. Pas vraiment le même but
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  12. #12
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Sauf votre respect, l'insertion dans une liste triée est un algorithme en O(N), tandis que l'insertion dans une map, basée sur un RB-tree, se fait en O(log2(N)), donc l'insertion dans la map sera nécessairement plus rapide que l'insertion dans la liste dès que N aura dépassé un treshold relativement faible.
    Si le but est d'insérer d'abord, (ou si les insertions se font "par lots", ce qui est le cas de presque toutes les utilisation de map en tables associatives), ce n'est pas vrai...

    Insérer N éléments dans un vector, par push_back, c'est O(N). Trier le vector ensuite, c'est N lg(N): au total, ca nous fait N lg(N)

    Insérer N éléments dans une map, c'est N lg(N), mais je suis près à parier que le coefficient dominant est en faveur du vecteur (parce qu'un vecteur c'est nettement plus facile à construire qu'un rb tree, et que quicksort, c'est comme son nom l'indique)

    Et, dans le cas de gros volumes de données, il faut ajouter l'overhead mémoire : un vector, ca prend à peine plus que les données qu'il contient, une map...

    Citation Envoyé par Emmanuel Deloget Voir le message
    Idem pour les recherches.
    Ah là surement pas... Les deux sont lg(N) puisque le vector est trié. Mais regardez à l'occasion le code de binary_search() (ou les autres algos de recherche utilisés sur des vecteurs triés) et celui de map::find(). Les déplacements lors de la recherche binaire, ce sont des additions de pointeur, pour un rb tree, on se balade dans une structure bien plus complexe, je ne parierais pas sur le rb tree...

    Citation Envoyé par Emmanuel Deloget Voir le message
    Sauf votre respect (hein ? deux fois ? ), std::map<> et std::vector<> rendent des services qui sont très différents. On utilise les maps pour associer une instance à une clef, et un vecteur est utilisé pour stocker une liste d'instances. Pas vraiment le même but
    Je suis d'accord avec la première phrase, mais pas avec la seconde. Un vector de paires triées fait parfaitement office de tableau associatif. En fait, c'est la bonne solution pour un tableau statique (c'est à dire dont le contenu ne change pas beaucoup après son chargement initial, ou qui est chargé par lots). Il sera plus rapide au chargement, à la recherche et aura une empreinte mémoire plus faible...

    Si l'on voulait faire mieux, il faudrait prendre une table de hachage (on sacrifie de la mémoire, mais on gagne en vitesse de recherche), mais là c'est plus délicat et moins standard.

    Une map n'est, a priori, une bonne table associative que si le tableau est dynamique, c'est à dire si on ajoute et enlève des clefs en cours de route, suffisamment souvent pour que cela pénalise le vector (et là il faut se méfier, parce que un insert de temps en temps, ce n'est pas très lourd, si le vector a fait gagner beaucoup de temps en recherche)

    Les conteneurs STL se distinguent par les garanties qu'ils offrent sur leurs opérations de base, pas par les données qu'ils sont censés accommoder.

    Francois

  13. #13
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Y'a d'ailleurs eu un topic assez conséquent sur cette question map vs vecteur de pair (tuple). Démarrer par toi fchartron si je me trompe pas?
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  14. #14
    Invité
    Invité(e)
    Par défaut
    Y'en a pas eu qu'un seul (et je ne suis pas sur que c'était moi qui avais commencé)... Récemment, je crois que Mac Lak en parlait sur le fil Langage D...

    Mais je vais ouvrir un autre fil sur les multimaps, parce que plus ca va, moins je comprends à quoi ca peut servir (je veux dire, c'est même pas un tableau associatif, y'a plus d'opérateur [] digne de ce nom, soit c'est un multiset qui ne s'avoue pas, soit c'est un vector trié qui ne se connait pas...)

    Francois
    Dernière modification par Invité ; 06/02/2010 à 22h40.

  15. #15
    Membre émérite

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Points : 2 252
    Points
    2 252
    Par défaut
    Pour l'utilité des maps vs vecteur de paire vs multimap et tutti quanti... On peut toujours tenter une approche par l'expérience. J'ai sur mon PC les sources du projet LLVM+Clang, c.a.d environ 1/2 millions de ligne de C++. Quelques recherches globales sur les différents conteneurs permettent de se faire une idée de leur utilité relative (le défaut étant qu'on manque tous les typedef, mais pour une première approximation c'est déjà bien)

    On obtient :

    Conteneur : occurrences

    std::string : 3490
    llvm::SmallVector : 2606
    std::vector : 2444
    llvm::StringRef : 1549
    llvm::denseMap : 1089
    std::map : 449
    llvm::StringMap : 306
    std::set : 245
    llvm:SmalString : 216
    std::vector<std::pair : 142
    llvm::denseSet : 95
    ]llvm::SmallSet : 80
    std::mulitmap : 57
    std::list : 38
    std::deque : 19
    std::multiset : 0 !

    Tiens, 448 occurrences de std::map contre 142 std::vector<std::pair ?
    Il faudrait vraiment dire à ces branquignolles que leur projet n'est pas "sérieux". Tout juste bon pour du "prototypage" LLVM

  16. #16
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Quand au warning, tu peux l'ignorer complètement. Il précise juste que vu la longueur de l'identifiant généré, le linker pourrait avoir du mal à y retrouver ses petits - en pratique, ce n'est que très très très rarement le cas (je ne l'ai jamais rencontré, malgré des années de MFC+STL)

    En fait, je te suggère de rajouter une ligne #pragma warning(disable:4786) (ou approchant ; je ne me rappelle plus exactement) dans ton fichier stdafx.h, avant toute inclusion de fichier.
    Je confirme, c'est un problème notamment dans Visual C++ 6.0 : c'est pénible, ça génère des tonnes de warning à la moindre compilation en mode Debug, mais ça n'a aucune incidence réelle. Le problème n'existe plus dans VS 2008 et au delà, à vérifier pour les versions entre VC6 et VS2008.

    Donc, un coup de #pragma et zou, t'es tranquille pour celui-là.

    Au passage, je te confirme aussi que la commande est bien :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    #pragma warning(disable: 4786)    // Disable warning "identifier was truncated to '255' characters in the browser information", for STL entities.

    Pour les maps, c'était bien sur le fil "Langage D", mais c'était à propos de la simplicité d'appel de l'opérateur [] et des propriétés. Les maps n'étaient citées que pour l'exemple d'un opérateur "pratique", mais compatible avec le langage C++ tel qu'il existe à l'heure actuelle.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  17. #17
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Tiens, 448 occurrences de std::map contre 142 std::vector<std::pair ?
    Il faudrait vraiment dire à ces branquignolles que leur projet n'est pas "sérieux". Tout juste bon pour du "prototypage" LLVM
    Mouais, et si tu fais la même recherche sur les composants d'interface d'un gros programme, tu vas voir que les boutons OK et Annuler gagnent haut la main, et que l'arbre, la grille ou le chaipaquoi qui est au coeur du truc n'existe qu'en un exemplaire... Pareil pour les appels de fonction, d'ailleurs, la fonction super sérieuse de la mort n'est appelée qu'une fois ou deux (au centre), par contre tu as des milliers de conversions et autres routines d'arrondi dans tous les coins.

    Ce qu'il faudrait regarder, c'est ce qui est utilisé dans les cas où les volumes et la complexité des traitement sont critiques...

    Et puis, ce genre d'analyse montre surtout la facon dont une équipe projet travaille, ses habitudes, les règles de codages. On doit pouvoir trouver de gros gros projets sans boost, d'énormes projets avec peu de STL, ou sans tel ou tel composant. J'ai connu de gros logiciels très réussis sans template (le CP y était allergique, car il les considérait indébugables).

    Enfin, même s'ils utilisaient des maps au lieu des vector triés, dans des cas où c'est une mauvaise idée, cela ne rendrait pas le projet moins sérieux, juste un peu plus gourmand en ressources qu'il le pourrait. Je connais des tas d'excellents informaticiens qui n'ont aucun problème avec ça... (voire qui en tirent une certaine fierté : il a fallu racheter une machine plus puissante pour faire tourner notre programme)

    Francois

  18. #18
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par fcharton Voir le message
    On doit pouvoir trouver de gros gros projets sans boost, d'énormes projets avec peu de STL, ou sans tel ou tel composant. J'ai connu de gros logiciels très réussis sans template (le CP y était allergique, car il les considérait indébugables).
    Je bosse justement sur un projet de ce type : pas de Boost, STL limitée au maximum et/ou au code non-critique, et les templates de façon générale ne sont pas en odeur de sainteté... Et c'est pourtant un "gros gros projet" !
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  19. #19
    Membre chevronné
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 33
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Points : 2 205
    Points
    2 205
    Par défaut
    Pour la STL je comprends, contraintes de performances etc. Pour boost j'ai déjà plus de mal et encore. Mais pour les templates là je vois carrément pas. Tout ce passant at compile time je vois pas le soucis...
    "Hardcoded types are to generic code what magic constants are to regular code." --A. Alexandrescu

  20. #20
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par Goten Voir le message
    Pour la STL je comprends, contraintes de performances etc. Pour boost j'ai déjà plus de mal et encore. Mais pour les templates là je vois carrément pas. Tout ce passant at compile time je vois pas le soucis...
    Oh, très simple, je t'explique :
    • Il faut savoir que l'on utilise déjà des librairies d'abstraction, comme ACE, POCO ou encore ICE, qui fournissent déjà pas mal de services.
    • STL : en embarqué, c'est "mauvais" sur le code critique, les algos spécialisés sont meilleurs même s'ils sont plus longs à écrire et plus difficiles à maintenir.

      On ne l'utilise guère qu'en prototypage, ou pour les sections non-critiques.
    • Boost : n'existe pas sur toutes les plate-formes que nous utilisons, or le code doit être le plus identique possible sur chacune. Il n'y a que certaines parties de Boost totalement portables, et qui (en gros) ne font pas vraiment mieux que la STL ou le code des librairies d'abstraction.

      Donc, pas de Boost, ce serait une maintenance coûteuse pour un gain très faible.
    • Templates : versions de compilateurs différents, dont certains relativement vieux et supportant mal les templates. De plus, c'est assez souvent infect à débugger.
      Autre problème : les templates peuvent générer beaucoup (trop) de code, et donc augmenter le footprint des programmes de façon assez démentielle.

      Donc, templates réduits au maximum possible, en gros largement en deça de ce qui est fait dans la STL.

    Pour ceux qui passent par hasard, et qui ne le sauraient pas, je bosse dans l'embarqué temps réel, donc avec des compilos parfois exotiques et des contraintes de performances bien au delà de ce que l'on connait sur un PC.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

Discussions similaires

  1. Problème avec mapping via Hibernate Synchronizer
    Par meijin_ryu dans le forum JDBC
    Réponses: 2
    Dernier message: 24/06/2012, 15h48
  2. Problèmes avec map et chaînes en tant que clé
    Par oodini dans le forum SL & STL
    Réponses: 4
    Dernier message: 15/09/2008, 18h00
  3. [STL]Problème avec map
    Par mambo dans le forum SL & STL
    Réponses: 11
    Dernier message: 27/07/2006, 15h39
  4. [PERL] Problème avec map
    Par LE NEINDRE dans le forum Langage
    Réponses: 9
    Dernier message: 05/10/2005, 09h48
  5. Problème avec memory mapping
    Par gemai dans le forum C
    Réponses: 13
    Dernier message: 04/07/2003, 09h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo