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
    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

    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

    La for range loop est disponible depuis C++11 : https://en.cppreference.com/w/cpp/la...uage/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
    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
    merci beaucoup pour vos explications bien détaillées

###raw>template_hook.ano_emploi###