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 :

question sur la surcharge d'opérateur ++


Sujet :

C++

  1. #1
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut question sur la surcharge d'opérateur ++
    J'ai une question concernant la surdéfinition des opérateur pour les itérateurs.
    Dans le code du header <iterator> de la STL, à la ligne 46, on a:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    	_Myt& operator++()
    		{	// pretend to preincrement
    		return (*this);
    		}
     
    	_Myt operator++(int)
    		{	// pretend to postincrement
    		return (*this);
    		}
    Je ne comprends pas du tout le fonctionnement du deuxième opérateur. Surtout, a quoi correspond et sert le (int)? il s'agit d'une fonction, mais elle ne possède pas d'argument. Il y a juste la déclaration du type.

    Enfin, pourquoi la préincrémentation renvoie une référence, alors que la posteincrémentation renvoie une valeur?



    Merci

  2. #2
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    En C et C++,il n'est pas obligatoire de nommer les arguments que l'on n'utilise(on doit juste donner leur type). L'argument int sert (au compilateur) à differencier post- et pre- incrementation. Enfin le renvoi d'une reference et d'une valeur est,ici, une question de sémantique : la préincremntation incremente l'objet et le renvoie, alors que la postincrementation incremente l'objet et renvoie une copie de l'objet avant l'incrementation. Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int i = 0;
    ++(++i) // i == 2
    (i++)++ // i == 3 equivalent de int tmp = i; i+=1; tmp++;
    Mais là, vu que ce sont sans doute de faux iterateur(dans le sens ou ils n'itèrent) comme back_inserter, la difference n'est pas très visible.

  3. #3
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    oui, mais quand on fait quelque chose comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     std::vector<double> T;
    	 T.push_back(1);T.push_back(2);T.push_back(3);T.push_back(4);
    	 std::back_insert_iterator<std::vector<double>> p(T),q(T);
    	  p++;
    	  ++p;
    on est d'accord que dans l'appel p++, on fait appel à la post-incrémentation.
    En fait, cela revient à faire:

    Mais dans ce cas, comment faire la différence entre la post incrémentation, et la pré-incrémentation.

  4. #4
    Modérateur
    Avatar de bruno_pages
    Homme Profil pro
    ingénieur informaticien à la retraite
    Inscrit en
    Juin 2005
    Messages
    3 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : ingénieur informaticien à la retraite
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Juin 2005
    Messages : 3 545
    Par défaut
    p.operator++() : préincrément
    p.operator++(0) : postincrément

    Citation Envoyé par deubelte Voir le message
    Mais dans ce cas, comment faire la différence entre la post incrémentation, et la pré-incrémentation.
    que voulez-vous dire ?
    Bruno Pagès, auteur de Bouml (freeware), mes tutoriels sur DVP (vieux, non à jour )

    N'oubliez pas de consulter les FAQ UML et les cours et tutoriels UML

  5. #5
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    que voulez-vous dire ?
    Vous avez répondu à ma question.

  6. #6
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    En fait, dans le meilleur des mondes, on aurait probablement :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    T& ++operator();
    T operator++();
    Mais j'imagine que ça n'a pas été retenue par le comité car cela compliquerait horriblement le boulot des parseurs uniquement pour supporter le cas particulier de la préincrémentation.

    Donc il a été choisi de différencier les deux opérateurs uniquement par la signature, avec aucun argument pour la préincrémentation et un int pour la postincrémentation.

  7. #7
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    Pour continuer sur les itérateurs, je voudrais savoir quelle est la différence entre ces deux opérateurs.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    	_Myt& operator=(const _Valty& _Val)
    		{	// push value into container
    		container->push_back(_Val);
    		return (*this);
    		}
     
    	_Myt& operator=(_Valty&& _Val)
    		{	// push value into container
    		container->push_back(_STD forward<_Valty>(_Val));
    		return (*this);
    		}
    Dans quel cas on appelle le second?

    Surtout, je pensais que les && (références sur références étaient illégales).
    Alors je ne vois pas trop comment appeler une fonction qui a comme type de paramètres qqch comme &&.

    Prenons une fonction tout simple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    int f(int &&a){
    return a;
    }
    Comment appeler cette fonction f?


    Merci

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Le second opérateur ( type & operator=(type &&) ) a été rajouté en C++11 (la nouvelle norme) et utilise ce que l'on appelle les rvalue reference.

    Elles peuvent être utilisées dans le cas où il est préférable de recourir à la move semantic plutôt qu'à la copie de l'objet passé en paramètre.

    Tu trouvera quelque informations sympa à ce sujet par exemple ici

    Si tu regarde autour du code du deuxième opérateur que tu présente, tu devrais avoir un ifdef ou un if defined quelconque permettant de s'assurer que l'on travaille en C++11
    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

  9. #9
    Membre éprouvé
    Inscrit en
    Novembre 2006
    Messages
    1 073
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 1 073
    Par défaut
    j'ai récupéré cela de visual studio C++ 2010. Je pense que la version 2008 n'avait pas ce genre de code.


    Mais sinon, comment appeler la fonction f (c'était ma dernière question).

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 635
    Par défaut
    Sauf erreur, le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Type obj(/* paramètres */);
    foo(obj);
    appellera la version prenant une référence constante alors que le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foo(Type(/*paramètres */));
    appellera la version prenant une rvalue reference... Mais c'est à vérifier (il me semble que les rvalue references et la move semantic ont déjà été abordées sur le forum... mais il faudra chercher ou )
    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

  11. #11
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Sauf erreur, le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Type obj(/* paramètres */);
    foo(obj);
    appellera la version prenant une référence constante alors que le code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foo(Type(/*paramètres */));
    appellera la version prenant une rvalue reference... Mais c'est à vérifier (il me semble que les rvalue references et la move semantic ont déjà été abordées sur le forum... mais il faudra chercher ou )
    Dans les deux, c'est la fonction prenant la r-value reference qui est appelée.
    Pour s'en rappeler, il suffit de se dire que r-value reference = variable anonyme.
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

  12. #12
    Invité
    Invité(e)
    Par défaut
    Si je ne me trompe pas, dans le premier cas la variable n'est pas anonyme(ou alors je n'ai rien compris à l'anonymat ?)

  13. #13
    Membre Expert

    Inscrit en
    Mai 2008
    Messages
    1 014
    Détails du profil
    Informations forums :
    Inscription : Mai 2008
    Messages : 1 014
    Par défaut
    Oui Joe, le premier code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Type obj(/* paramètres */);
    foo(obj);
    appelle la version par const ref, car on passe à foo() une l-value, c'est à dire une variable nommée (son nom est "obj") dont on peut prendre l'adresse.
    Le deuxième code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foo(Type(/*paramètres */));
    appelle la version par ref ref, car on passe à foo() une r-value, c'est une dire une variable anonyme, temporaire, dont on ne peut pas prendre l'adresse.

  14. #14
    Rédacteur

    Avatar de Davidbrcz
    Homme Profil pro
    Ing Supaéro - Doctorant ONERA
    Inscrit en
    Juin 2006
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ing Supaéro - Doctorant ONERA

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 307
    Par défaut
    Citation Envoyé par Arzar Voir le message
    Oui Joe, le premier code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Type obj(/* paramètres */);
    foo(obj);
    appelle la version par const ref, car on passe à foo() une l-value, c'est à dire une variable nommée (son nom est "obj") dont on peut prendre l'adresse.
    Le deuxième code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    foo(Type(/*paramètres */));
    appelle la version par ref ref, car on passe à foo() une r-value, c'est une dire une variable anonyme, temporaire, dont on ne peut pas prendre l'adresse.
    OMG, j'ai lu trop vite, j'ai cru que obj était une fonction renvoyant un objet du type Type. Dans ce cas, mes posts sont à supprimer ^^
    "Never use brute force in fighting an exponential." (Andrei Alexandrescu)

    Mes articles dont Conseils divers sur le C++
    Une très bonne doc sur le C++ (en) Why linux is better (fr)

Discussions similaires

  1. Question sur la surcharge de constructeur avec enum ?
    Par LiTiL_DiViL dans le forum Débuter avec Java
    Réponses: 3
    Dernier message: 05/04/2013, 12h53
  2. Question sur la surcharge buffer
    Par sivaller dans le forum OpenGL
    Réponses: 1
    Dernier message: 04/04/2008, 00h02
  3. [debutant] question sur la surcharge des operateurs
    Par hunter99 dans le forum Débuter
    Réponses: 17
    Dernier message: 04/01/2008, 18h26
  4. Questions sur l'opérateur <<
    Par coyotte507 dans le forum C++
    Réponses: 4
    Dernier message: 18/11/2007, 22h54
  5. question sur les opérateurs
    Par isidore dans le forum C++
    Réponses: 10
    Dernier message: 25/02/2005, 18h46

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