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

C++ Discussion :

diff�rence entre it�rateurs et operator[]


Sujet :

C++

  1. #1
    Membre actif
    Homme Profil pro
    �tudiant
    Inscrit en
    Octobre 2012
    Messages
    10
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 10
    Par d�faut diff�rence entre it�rateurs et operator[]
    Bonjour,

    Pour mon projet, j'ai besoin de recuperer un "block" a une position donn�e et v�rifier son Type.

    J'ai donc fais ce code :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    if (pos < this->map.size())                                                                         
        {                                                                                                 
          Block *tmp = map[pos];                                                                          
          if (tmp->getTypeBlock() != EMPTY && tmp->getTypeBlock() != EXPLOSION)                           
            return false;                                                                                 
        }                                                                                                 
      return true;
    Normalement mon programme devrait rentrer dans le "if " mais il ne le fait pas.

    J'ai test� ce code :

    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
     
    std::vector<Block *>::iterator it = this->map.begin(); 
     
     while (it != this->map.end())                                                                       
        {                                                                                                 
          type = (*it)->getTypeBlock();                                                                                                                      
          if (type != EMPTY && type != EXPLOSION)                                                         
            {                                                                                             
              block_x = (*it)->getX();                                                                    
              block_y = (*it)->getY();                                                                    
              if (block_y == y && block_x == x)                                                           
                break;                                                                                    
            }                                                                                             
          ++it;                                                                                           
        }                                                                                           
      return (true);
    Mon programme passe dans le if.

    J'ai donc print les positions en x et en y de mon "block" pour les deux versions du code, se sont les m�mes.

    J'ai donc pour deux versions le m�me block mais avec un "Type" diff�rent en fonction du type d'approche que j'ai (it�rateurs et []).

    Je ne vois pas d'ou �a peut venir... Une id�e ?

    Merci d'avance.

  2. #2
    Inactif  


    Homme Profil pro
    Doctorant s�curit� informatique � Dipl�m� master Droit/�conomie/Gestion
    Inscrit en
    D�cembre 2011
    Messages
    9 026
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 32
    Localisation : France, Loire (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : Doctorant s�curit� informatique � Dipl�m� master Droit/�conomie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : D�cembre 2011
    Messages : 9 026
    Par d�faut
    Bonjour,

    Il nous est assez difficile de vous aider sans un code minimal reproduisant les effets que vous observez.

    Dans le premier cas, vous acc�dez � l'�l�ment gr�ce � une seule dimension (pos) et dans le second gr�ce � deux dimensions (x et y) et nous ne savons m�me pas comment vous passez d'une coordonn�e en deux dimensions (x, y) � une coordonn�e � une dimension (pos).

  3. #3
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Salut,

    De mani�re g�n�rale, un it�rateur est un objet qui permet de parcourir l'ensemble de la collection (comme par hasard, le terme vient du verbe "it�rer" )
    De son cot�, l'op�rateur [] permet d'acc�der directement � la donn�e dont l'index est indiqu�.

    Les it�rateurs sont souvent associ�s aux boucles qui doivent s'effectuer dans l'interval repr�sent� par l'it�rateur renvoy� par la fonction begin() (qui renvoie un it�rateur sur le premier �l�ment de la collection) et celui renvoy� par la fonction end() (qui renvoie un it�rateur sur... ce qui suit le dernier �l�ment) ainsi qu'aux fonction find (et autres fonctions similaires) qui renverront l'it�rateur sur l'objet qui correspond (s'il existe) ou sur l'it�rateur qui serait renvoy� par la fonction end() pour indiquer que l'objet n'a pas �t� trouv�.

    L'�norme avantage, c'est que nous sommes donc certains de travailler dans un intervalle pr�cis qui est de l'ordre de [begin(), end()[

    C'est d'autant plus vrai que l'op�rateur [] de std::map a un comportement sp�cifique dans le sens o� il ajoutera automatiquement un �l�ment dont la cl� correspond � celle que l'on a donn� dans l'op�rateur si la cl� n'existe pas encore.

    Et c'est un comportement normal : l'op�rateur [] renvoie une r�f�rence (�ventuellement constante) sur l'objet qui correspond � la cl� indiqu�e.

    Pour que cet op�rateur puisse marcher, il faut... qu'il existe bel et bien un �l�ment correspondant � la cl� indiqu�e

    Si la cl� n'existe pas, il faudra donc rajouter une pair cl� / valeur dont la cl� correspondra � celle que l'on a utilis�e et dont la valeur sera le r�sultat... du constructeur par d�faut de l'objet en question.

    Mais je crois que tu n'as peut etre pas parfaitement compris le principe du fonctionnement de la std::map (ou, du moins, le code que tu pr�sentes peut le laisser penser).

    Il faut donc savoir que std::map est ce que l'on appelle un "tableau associatif".

    C'est � dire qu'il s'agit d'une collection dans laquelle chaque �l�ment sera associ� � une cl�s qui lui est propre.

    Il y a donc une tr�s forte corr�lation entre la cl� (AKA: ce que tu pourrais placer entre les []) et l'�l�ment correspondant.

    Les raisons qui poussent � utiliser une std::map sont donc celles qui feront que tu voudrais pouvoir acc�der � un �l�ment particulier sur base d'une valeur qui n'est pas forc�ment fournie (ni m�me accessible) par l'�l�ment en question.

    Ainsi, tu pourrais tr�s bien avoir une std::map<int, int> qui serait remplie sous une forme proche de
    std::map<int, int> lamap
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    for(int i = 1; i < 11; ++i){
        lamap[i*2]=i;
    }
    dont chaque �l�ment (les valeur de 1 � 10 inclus) serait repr�sent� par une cl� dont la valeur est �gale au double de celle de l'�l�ment.

    Par cons�quent, si tu invoques la fonction size de "lamap", tu obtiendras une valeur �gale � 10 (car il y aura bel et bien 10 paires "cl� / valeur" dans la collection) mais les seules valeurs que tu pourrait placer entre les crochets pour obtenir un �l�ment existant seraient 2, 4, 6, 8, 10, 12, 14, 16, 18 et 20 car il n'y a, jusqu'� pr�sent du moins, aucune cl� dont la valeur serait impaire.

    Aussi, lorsque je vois le code
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    if (pos<this->map.size())
    {
        Block *tmp = map[pos];     
        if (tmp->getTypeBlock() != EMPTY && tmp->getTypeBlock() != EXPLOSION)
        return false;
    }
    ... j'ai franchement peur

    Peut etre as tu d�j� quel sera le probl�me

    Bah, au cas o� tu ne l'aurais pas compris, cela ne fait rien, car je vais te l'expliquer...

    Je te rappelle que, dans la situation dans laquelle j'ai laiss� lamap, lamap.size() est �gal �... 10!!!
    Oui, mais, du coups, si j'�cris le code
    je n'autorise que les valeurs 0,1, 2, 3, 4, 5, 6, 7, 8, et 9 (et toutes les valeurs n�gatives, mais l'explication est d�j� assez complexe sans les prendre en compte), et sur ces dix valeurs, seules 4 (2, 4, 6 et 8) correspondent � une cl� qui existe d�j�.

    Du coup, la suite du code va avoir deux effets pervers:
    • Non seulement, tu ne vas tester que la moiti� des �l�ments qui se trouvent dans lamap,
    • Mais, en plus, le fonctionnement de l'op�rateur[] de std::map aidant, tu vas rajouter les cl�s 1, 3, 5, 7 et 9
    Et ce deuxi�me comportement sera particuli�rement d�sagr�able car, dans le "meilleur des cas" il cr�era un objet par d�faut (un int ayant pour valeur 0 ou un pointeur ayant pour valeur NULL (nullptr en C++11) ), dans le pire des cas, il cr�era un objet dont la valeur correspond... aux "crasses" laiss�es en m�moire par une utilisation pr�c�dente

    Dans mon code d'exemple, et avec un peu de chance, cela ne devrait pas poser �norm�ment de probl�me car, en �crivant quelque chose comme
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    if(pos <lamap.size()) // mettons que pos ==3
    {
        int temp = lamap[pos]; // "avec un peu de chance" temp == 0
    }
    cela ne devrait pas poser *�norm�ment* de probl�me

    Mais, avec ton code... ouchh!!! Bobo !!!

    Voyons pourquoi!
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    if (pos<this->map.size()) // mettons : pos < map.size() MAIS pos correspond à une clé inexistante
    {
        Block *tmp = map[pos]; // CRACK!!!"dans le meilleur des cas" tmp == NULL
        if (tmp->getTypeBlock() != EMPTY && tmp->getTypeBlock() != EXPLOSION)  //BOUMM!! déréférencement de NULL
        return false;
    }
    Dans "le meilleur des cas", si pos est bel et bien plus petit que map.size() mais que pos ne correspond � aucune cl�, ton pointeur temp correspond � NULL (nullptr en C++11).

    Essayer d'acc�der � une fonction membre au d�part de NULL correspond � un comportement ind�fini qui a de fortes chances de se traduire par... une erreur de segmentation (un crash de l'application, purement et simplement).

    Dans le pire des cas, tu obtiendras quelque chose qui "peut passer pour une adresse valide". Apr�s tout, un pointeur n'est jamais qu'une valeur num�rique enti�re (g�n�ralement non sign�e) qui correspond � l'adresse m�moire � laquelle on trouvera l'�l�ment du type indiqu�.

    Et l�, ben, il peut arriver du grand tout et n'importe quoi

    Tu pourrais, tout aussi bien voir une explosion au milieu de ton �cran, alors qu'il n'en faut pas (pas cool ) que de ne rien avoir (plus cool) mais, �tant donn� que tu n'auras pas forc�ment parcouru l'ensemble de ta map, tu pourrais aussi ne pas voir une explosion qui aurait du se produire (pas cool non plus)

    Maintenant, si tu es sur (mais vraiment sur et certain!!!) qu'il existe bel et bien un pointeur valide pour toute cl� correspondant � pos tel que pos < map.size(), que tu n'oublieras aucune cl� dans ces circonstances, et qu'il n'y a aucun "trou" entre tes cl�s (comprend : que toutes les cl�s comprises entre 0 et map.size() existent bien), cela pourrait encore passer, mais... Es-tu en mesure de le garantir
    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
    Inactif  


    Homme Profil pro
    Doctorant s�curit� informatique � Dipl�m� master Droit/�conomie/Gestion
    Inscrit en
    D�cembre 2011
    Messages
    9 026
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 32
    Localisation : France, Loire (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : Doctorant s�curit� informatique � Dipl�m� master Droit/�conomie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : D�cembre 2011
    Messages : 9 026
    Par d�faut
    @Koala01 :
    map est un std::vector dans son code :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    std::vector<Block *>::iterator it = this->map.begin();

  5. #5
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Citation Envoy� par Neckara Voir le message
    @Koala01 :
    map est un std::vector dans son code :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    std::vector<Block *>::iterator it = this->map.begin();
    Ouuupss... je me suis laiss� eu par le nom... au temps pour moi
    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
    Membre Expert
    Avatar de imperio
    Homme Profil pro
    �tudiant
    Inscrit en
    Mai 2010
    Messages
    872
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rh�ne Alpes)

    Informations professionnelles :
    Activit� : �tudiant
    Secteur : High Tech - �diteur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 872
    Par d�faut
    Pourquoi j'ai l'impression que c'est le code d'un bomberman que voil� ?

    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
    std::vector<Block *>::iterator it = this->map.begin(); 
     
     while (it != this->map.end())                                                                       
        {                                                                                                 
          type = (*it)->getTypeBlock();                                                                                                                      
          if (type != EMPTY && type != EXPLOSION)                                                         
            {                                                                                             
              block_x = (*it)->getX();                                                                    
              block_y = (*it)->getY();                                                                    
              if (block_y == y && block_x == x)                                                           
                break;                                                                                    
            }                                                                                             
          ++it;                                                                                           
        }                                                                                           
      return (true);
    Pourquoi ne pas remplacer le break par un return true ?

    Sinon je te recommande d'utiliser les it�rateurs dans ce genre de cas plut�t que d'aller lire les cases une par une. Heureusement le post de koala01 explique cela tr�s bien.

  7. #7
    Membre actif
    Homme Profil pro
    �tudiant
    Inscrit en
    Octobre 2012
    Messages
    10
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activit� : �tudiant

    Informations forums :
    Inscription : Octobre 2012
    Messages : 10
    Par d�faut
    @koala01 : Oui le nom laissait � penser que c'�tait une map.. Merci quand m�me pour tes explications bien d�taill�es .

    Pourquoi ne pas remplacer le break par un return true ?
    En effet, dans la version "original" j'ai mis un return true, mais la j'avais mis l'exemple juste pour illustrer mes propos.. Donc le break est une erreur de ma part.

    Apr�s quelques heures de debug, j'ai trouv� d'ou venait le probl�me. Il venait de bien plus haut dans le code, je n'appelais pas la bonne m�thode.

    Merci de votre aide !

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Diff�rence entre un "bidouilleur" et un Pro ?
    Par christ_mallet dans le forum D�bats sur le d�veloppement - Le Best Of
    R�ponses: 290
    Dernier message: 28/11/2011, 10h53
  2. diff�rence entre it�rateur et indice ( [] )
    Par ooxoo dans le forum SL & STL
    R�ponses: 29
    Dernier message: 21/09/2008, 18h52
  3. Diff�rence entre TCP, UDP, ICMP
    Par GliGli dans le forum D�veloppement
    R�ponses: 1
    Dernier message: 13/09/2002, 08h25
  4. Diff�rences entre jmp, jz, jnz, etc
    Par christbilale dans le forum Assembleur
    R�ponses: 3
    Dernier message: 05/07/2002, 15h09
  5. R�ponses: 3
    Dernier message: 07/05/2002, 16h06

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