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

Langage C++ Discussion :

utilité des itérators


Sujet :

Langage C++

  1. #1
    Membre du Club
    Homme Profil pro
    Inscrit en
    août 2013
    Messages
    270
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : août 2013
    Messages : 270
    Points : 56
    Points
    56
    Par défaut utilité des itérators
    Bonjour à tous,

    je vous donne un exemple ca sera plus parlant sur mon probleme.
    Voici une classe A.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    classe A{
    public:
    A(int value) : m_value(value){}
     
    int m_value = 0;
    };
    et le main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int main(){
    std::vector<A> tab = { A(10), A(20), A(30), A(40) };
     
    for( const auto & t : tab )
    {
    std::cout << t.m_value << std::endl;
    }
    }
    ou alors dans le main :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main()
    {
    std::vector<A> tab = { A(1), A(2), A(3), A(4)};
     
    std::vector<A>::iterator it;
     
    for ( it = tab.begin(); it != tab.end(); ++it)
    {
    	cout << (*it).m_value << endl;
    }
    je ne vois pas en quoi la seconde méthode est plus performante. De plus j'ai lu que l'utilité des itérators c'est qu'on avait le meme code pour les différents conteneurs, or je peux tres bien utiliser for(const auto & t : tab) pour n'importe quel conteneur.

    Merci d'avance pour vos éclaircissements.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    6 211
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 6 211
    Points : 28 165
    Points
    28 165
    Billets dans le blog
    2
    Par défaut
    Oui la for ranged loop est bien meilleure que les itérateurs maintenant.
    Plus simple d'utilisation et niveau source d'erreur on frôle le nul.
    Et en interne il utilise le principe des itérateurs puisqu'il faut une fonction begin et end pour que la syntaxe fonctionne.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  3. #3
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    ...
    Inscrit en
    juin 2009
    Messages
    4 303
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : ...

    Informations forums :
    Inscription : juin 2009
    Messages : 4 303
    Points : 12 952
    Points
    12 952
    Billets dans le blog
    1
    Par défaut
    La for range loop est disponible depuis C++11 : https://en.cppreference.com/w/cpp/language/range-for

    Les itérateurs étaient déjà là en C++98 / C++03

    PS : C++ Insights est bien utile des fois pour voir ce qu'il se passe sous le capot. Par exemple, on voit que le for range loop est traduit en...... for avec itérateur

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    octobre 2004
    Messages
    11 336
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : octobre 2004
    Messages : 11 336
    Points : 28 719
    Points
    28 719
    Par défaut
    Salut,

    De manière générale, un itérateur est un concept dont le but est de permettre ... d'itérer sur les différents éléments d'une collection sans avoir à s'inquiéter de la manière dont les éléments sont maintenus en mémoire au sein de cette collection.

    Quand on décide d'utiliser ce concept, on sait que l'on peut accéder au premier élément d'une collection quelconque à l'aide d'une fonction membre nommée begin() et on sait que la fonction end() permet d'accéder à ... ce qui suit le dernier élément valide contenu par cette même collection.

    En 2011, un certain nombre de fonctionnalités sympa sont apparues, telles que:

    1- L'inférence de type, qui permet de déterminer le type d'une variable sur base du type de retour de la fonction à laquelle on fait appel. C'est cool, parce que, si on a un tableau de chaines de caractères -- par exemple -- qui prend la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<std::string> tab;
    nous ne sommes plus obligés d'indiquer explicitement le type réel de l'information renvoyée par la fonciton begin, ce qui aurait pris la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<std::string>::iterator it = tab.begin();
    parce que c'est long et fastidieux.

    Et encore, j'ai mis la version courte, car std::string n'est qu'un alias de type sur std::basic_string<char, std::char_trait<char>, std::alocator<char>>. Je te laisse donc imaginer à quoi ressemblerait la version longue

    Désormais, grâce à l'inférence de type (et au mot clé auto), on peut se contenter d'un code qui prenne la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    auto it = tab.begin(); //it est de type "std::vector<std::string>::iterator
    Il faut comprendre que l'inférence de type n'a rien supprimé du tout, pas plus qu'elle n'a remplacé quoi que ce soit : toutes les fonctionnalités qui existaient avant C++11 existent encore en C++11, compatibilité avec le code existant oblige.

    L'inférence de type a juste apporté "une nouvelle possibilité" qui est
    • plus simple : un seul mot peut être utilisé pour désigner un type de donnée "à charnières et à rallonges"
    • plus souple : si je décide de remplacer le std::vector par un std::list ou par un std::set, je ne dois pas commencer à chercher tous les endroits dans le code où j'utilise un itérateur (et où je le défini comme étant le résultat renvoyé par la fonction begin()) afin d'en corriger le type
    • plus "élégante", d'un certain point de vue

    En un mot comme en cent, ce n'est pas parce que l'on utilise auto que l'on n'utilise plus les itérateurs : on décide "simplement" de s'offrir la possibilité d'être "moins attentif" à leur type réel.

    2- les range based loops (ou les boucle "basée sur des intervalles).

    Le comité s'est rendu compte que la manière "classique" (je devrais dire "historique") de parcourir les éléments d'une collection n'était pas "la plus facile qui soit", car elle est basée sur la syntaxe "historique" permettant de définir une boucle "pour", à savoir
    for( <type> <nom> = <valeur de départ>; <condition de sortie>; <passage à la valeur suivante>). Ce qui est assez lourd à écrire lorsqu'il s'agit de parcourir tous les éléments d'une collection dynamique.

    Et il a trouvé cela bien dommage, car, il s'est également rendu compte que toutes les collections proposées par la bibliothèque standard exposent les fonctions begin et end (qui permettent toutes les deux d'obtenir un itérateur sur le contenu de la collection), et parce qu'une grosse majorité des boucles que l'on est amené à créer dans les différentes situations qui impliquent des collections sont destinées à... parcourir l'ensemble des éléments que ces collections contiennent.

    L'un dans l'autre, certains langages avaient déjà donné le ton en permettant la création de boucles dont la signification est "pour chaque élément contenu par ma collection". Ce genre de boucle ne nécessite que deux éléments syntaxiques (contre trois pour les boucles "classiques"), à savoir:

    • un identifiant représentant la donnée qui contiendra chacun des éléments et
    • l'identifiant qui sert de collection

    étant entendu que ce nouveau type de boucle devra systématiquement parcourir tous les éléments que l'on peut croiser entre l'élément renvoyé par la fonction begin() et celui entre l'élément renvoyé par la fonction end().

    Encore une fois, les boucles basées sur les intervalles n'ont occasionné ni suppression ni remplacement au sein du langage et / ou de la bibliothèque standard : c'est une nouvelle possibilité qui utilise ingénieusement la présence d'éléments connus pour nous faciliter la vie en rendant l'usage de ces éléments implicites.

    Comme l'a si bien fait remarquer Btkaro, les boucles basées sur les intervalles ne font rien d'autre que de mettre en place une boucle "pour" qui s'appuie implicitement sur les fonctions begin et end. La seule différence, c'est qu'on n'est plus obligé d'y avoir recours de manière explicite

    3- d'autres joyeusetés, comme les pointeurs intelligents, la notion d'ownership, la sémantique de déplacement, les threads, les fonctionnalité de gestion fine du temps et d'aléatoire, et bien d'autres encore.

    Au final, il faut juste que tu te rende compte que ce n'est pas parce que tu ne semble plus avoir recours à "quelque chose" -- surtout si l'on parle d'une notion aussi "basique" et "d"usage général" que la notion d'itérateurs -- que tu n'a plus besoin de connaître cette notion:

    La connaissance de cette notion sert toujours de "mortier" permettant de relier "un certain nombre" (en augmentation, qui plus est) de possibilités entre elles, même si les nouvelles possibilités nous permettent d'être "moins attentif", de les utiliser presque "sans avoir à nous en rendre compte"
    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

  5. #5
    Membre du Club
    Homme Profil pro
    Inscrit en
    août 2013
    Messages
    270
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : août 2013
    Messages : 270
    Points : 56
    Points
    56
    Par défaut
    merci beaucoup pour vos explications bien détaillées

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utilité des types OpenGL GLint, GLfloat, GLvoid, etc.
    Par Djakisback dans le forum OpenGL
    Réponses: 17
    Dernier message: 14/12/2005, 13h35
  2. utilité des tables ??
    Par shadowmoon dans le forum Langage SQL
    Réponses: 6
    Dernier message: 02/06/2005, 10h43
  3. Utilité des schemas sous Postgresql?
    Par sessime dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 18/03/2005, 16h45
  4. Utilité des logos Xiti ?
    Par KibitO dans le forum Evolutions du club
    Réponses: 5
    Dernier message: 20/02/2005, 18h42
  5. utilité des DbControl
    Par portu dans le forum Bases de données
    Réponses: 6
    Dernier message: 02/07/2004, 06h41

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