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 :

les references en c++


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Inscrit en
    Novembre 2008
    Messages
    90
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 90
    Points : 36
    Points
    36
    Par défaut les references en c++
    bonjour ,

    j'ai consulté pas mal de tuto de c++ pour bien comprendre pourquoi on utilise les références en c++?; pour moi les variables globales peuvent régler le problème n'est ce pas

  2. #2
    Membre expert

    Profil pro
    imposteur
    Inscrit en
    Avril 2003
    Messages
    3 308
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : imposteur

    Informations forums :
    Inscription : Avril 2003
    Messages : 3 308
    Points : 3 377
    Points
    3 377
    Par défaut
    Les variables globales, c'est mal. Il faut limiter leur usage au maximum.

    D'une manière générale, on doit utiliser des variables définies de la manière la plus "étroite" possible par rapport aux besoins correspondants. Si une variable n'est requise que localement dans le corps d'une méthode, alors on la définira localement dans cette méthode, et pas dans la classe mère, et encore moins comme variable globale.

    Pourquoi c'est mal, les variables globales ?
    • Les variables globales peuvent poser des problèmes de débogage (les collisions entre variables sont difficiles à trouver, on peut penser utiliser des "i" différents alors qu'on modifie toujours la même variable, etc) ;
    • Elles handicapent la lecture d'un code source (c'est difficile de comprendre ce qui sert à quoi quand les variables sont déclarées n'importe où et peuvent être modifiées n'importe où) ;
    • Elles posent des problèmes de maintenance (si on doit faire évoluer le code source, il faut vérifier qui modifie quelle variable globale avant de faire quoi que ce soit, et les intrications peuvent être difficiles à gérer ; on ne peut pas faire de modifications de manière locale sans appréhender l'ensemble du code) ;
    • Elles peuvent poser des problèmes beaucoup plus complexes dans les applications multi-threads.

  3. #3
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Citation Envoyé par asprog Voir le message
    j'ai consulté pas mal de tuto de c++ pour bien comprendre pourquoi on utilise les références en c++?; pour moi les variables globales peuvent régler le problème n'est ce pas
    Les références ne sont pas là pour régler un problème de portée (enfin, pas seulement), elles permettent de désigner explicitement l'objet sur lequel tu veux travailler, et cela se passe en grande partie au moment de la compilation.

    Tu peux créer des aliases de noms de variables avec des références mais surtout, passer une référence en tant qu'argument de fonction permet de travailler directement sur l'objet passé plutôt que sur une copie et ce, sans avoir à utiliser les pointeurs. C'est particulièrement utile si tes objets sont gros.

    Quant aux variables globales, elles ont leur raison d'être, mais voici quelques raisons supplémentaires d'éviter autant que possible d'y recourir : http://www.developpez.net/forums/d93...c/#post5271611

  4. #4
    Nouveau membre du Club
    Inscrit en
    Novembre 2008
    Messages
    90
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 90
    Points : 36
    Points
    36
    Par défaut
    merci de m avoir donner ses explications.mais le concept de références reste

    tjrs ambiguë pour moi je vois pas l intérêt de l utilisation de référence dans

    mon code c++;est ce que je px avoir un exemple d utilisation de références

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

    Informations professionnelles :
    Activité : aucun

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

    Une référence permet de faire... référence () à une variable ou à un objet qui existe "en dehors" de la fonction appelée ou de l'objet en cours d'utilisation.

    Il faut en effet comprendre qu'il arrive très souvent que tu doive fournir à une fonction des informations qu'elle n'est absolument pas en mesure d'obtenir "par elle-même", généralement, parce que c'est informations sont susceptibles d'être créés / gérées / modifiées par d'autres fonctions prévues spécialement à cet effet, et que la gestion de ces information n'entre absolument pas dans la responsabilité de la fonction que tu appelle.

    On t'a déjà expliqué en long et en large pourquoi il n'est pas bon d'utiliser les variables globales, mais cela signifie donc qu'il faudra régulièrement passer des arguments à tes différentes fonctions.

    Cependant, quand tu passe un argument de manière "normale" (on dit "par valeur") à une fonction, tu provoque la copie de l'argument transmis, et toutes les modifications que tu pourrais apporter à ceux-ci ne seront pas répercutées sur la variable d'origine.

    De plus, il arrive régulièrement (pour toutes les classes qui ont sémantique d'entité) que l'on se rende compte qu'il n'est pas opportun de permettre la copie de l'objet et que l'on fasse donc en sorte d'interdire la copie.

    Mais ce n'est pas une raison pour empêcher de passer de telles variables aux fonctions qui en ont besoin, ni pour envisager d'utiliser des variables globales !!!

    Enfin, même pour les types personnels dont on estime qu'ils peuvent être copiés, il faut savoir que leur copie peut nécessiter beaucoup de ressources, tant en temps que du point de vue de la mémoire à utiliser.

    Il est donc globalement utile d'éviter les copies chaque fois que faire se peut, surtout pour les types personnalisés.

    Au final, on peut dire que cela devrait presque devenir une seconde nature de transmettre les arguments qui ne sont pas des types primitifs sous la forme de référence, voir, sous la forme de référence constante, si l'objet transmis en paramètre ne doit pas être modifié par la fonction appelante.

    Alors, si tu veux avoir un exemple particulier de l'utilisation des références, le mieux serait de nous montrer un code à toi, que l'on pourrait analyser afin d'en mettre les problèmes en évidences
    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
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    En C ou en C++, lorsque tu déclares une variable


    … ton compilateur réserve de la place et définit un symbole « x » qui permet de référer, au niveau sémantique, à cette variable. Tu peux donc créer explicitement un second symbole se référant à la même chose :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    int x;
    int & y = x;
     
    std::cout << (void *)&x << std::end; // Adresse mémoire de x
    std::cout << (void *)&y << std::end; // Adresse mémoire de y

    Code Shell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ g++ ref.c++ -o ref
    $ ./ref
    0x7fff06cc6c34
    0x7fff06cc6c34

    Une référence n'est donc pas un « objet » à proprement parler, en mémoire. C'est un symbole supplémentaire se référant à une même chose. La définir permet donc de spécifier « de quel objet on parle ». C'est aussi pour cette raison qu'elle ne peut pas être redéfinie a posteriori. C'est un calcul qui se fait au niveau de la compilation.

    Ensuite, utiliser les références dans les arguments de fonctions permet de passer ces arguments « par référence » plutôt que « par valeur » (explicite dans le Visual Basic, par exemple). Lorsque tu passes un argument à une fonction, celui-ci est considérée comme une variable locale de ladite fonction. Le fait de dire qu'il ne s'agit pas d'une variable mais d'une référence permet de travailler directement sur la variable d'origine. Exemple :

    Code C++ : 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
    23
    24
    25
    26
    27
    28
    29
    30
    #include <iostream>
     
    void ParValeur (int x)
    {
        x++;
        std::cout << "Valeur de x après incrémentation par ParValeur : " << x << std::endl;
    }
     
    void ParReference (int & x)
    {
        x++;
        std::cout << "Valeur de x après incrémentation par ParReference : " << x << std::endl;
    }
     
    int main (void)
    {
        int x;
     
        x = 4;
     
        std::cout << "Valeur de x avant entrée dans ParValeur : " << x << std::endl;
        ParValeur (x);
        std::cout << "Valeur de x après sortie de ParValeur : " << x << std::endl << std::endl;
     
        std::cout << "Valeur de x avant entrée dans ParReference : " << x << std::endl;
        ParReference (x);
        std::cout << "Valeur de x après sortie de ParReference : " << x << std::endl << std::endl;
     
        return 0;
    }

    Code Shell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ g++ parref.c++ -o parref
    $ ./parref
    Valeur de x avant entrée dans ParValeur : 4
    Valeur de x après incrémentation par ParValeur : 5
    Valeur de x après sortie de ParValeur : 4
    
    Valeur de x avant entrée dans ParReference : 4
    Valeur de x après incrémentation par ParReference : 5
    Valeur de x après sortie de ParReference : 5

    On voit bien que deux fonctions sont identiques, et que seul le « & » supplémentaire dans l'argument les différencie. On voit également que dans le premier cas, le « x » de la fonction main() est resté inchangé (la fonction n'a modifié que son propre argument) alors que sa valeur a changé à l'issue de la seconde fonction, parce que la fonction est bien déclarée comme « se référant à l'objet passé en argument ».

    En C, pour faire ceci, on utilise les pointeurs : tous les arguments sont passés par copie mais la valeur transmise est l'adresse mémoire de l'objet sur lequel on veut travailler.

    C'est très utile si l'argument en question n'est pas un simple entier mais un très gros objet comme une vidéo, par exemple. Ça te permet de travailler sur un objet unique sans avoir à en faire des centaines de copies en mémoire du simple fait du compilateur.

    Il est très important de remarquer, également, que les deux fonctions s'invoquent exactement de la même manière. Si tu ne vas pas jeter un œil au prototype, tu ne peux pas savoir a priori, en regardant le code de la fonction main(), si un argument est passé par valeur ou par référence, et c'est volontaire.

    Dernier exemple : tu peux également spécifier des références en sortie d'une fonction : lorsque tu fais

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    cout << "Valeur de x : " << x << endl;

    … « << » est un opérateur. Donc en fait une fonction membre de cout (ça peut être aussi une fonction ordinaire à deux arguments mais peu importe à ce stade). Tu fais en réalité :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    cout.operator << ("Valeur de x : ");

    Or, cet opérateur est déclaré de la sorte

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class ostream
    {
        ostream & operator << (const char *);
    }
    Ça signifie que tu invoques la fonction-membre de cout, que tu lui passes en argument la chaîne « "Valeur de x : " » et que l'opérateur en question te renvoie … une référence vers un objet de type ostream. Il se trouve qu'en l'occurrence, cet objet, c'est lui-même.

    Dès lors, le résultat de l'opération est l'objet de départ et tu peux donc, exactement de la même façon, rappeler un opérateur pour transmettre « x ». Les deux définitions ci-dessous sont donc équivalentes :

    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    cout.operator << "Valeur de x : " << x << endl;
    cout.operator << ("Valeur de x : ").operator << (x).operator (endl);

    Et ça, ce n'est possible que grâce aux références. Sinon, il faudrait explicitement passer par les pointeurs, qu'il faudrait « déréférencer » (c'est-à-dire suivre avec « -> » pour accéder à ce qu'ils pointent).

    Dernier exemple : j'ai le score de trois personnes différentes dans des variables x, y et z (je considère qu'il n'y a aucun ex-æquo). Et je souhaite accorder 10 points de bonus à celui qui a obtenu le plus haut score. Comment vais-je m'y prendre ?

    Code C++ : 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
    #include <iostream>
     
    int & VariableMaximum (int & x, int & y, int & z)
    {
        return (x>=y) && (x>=z)?x:y>z?y:z;
    }
     
    int main (void)
    {
        int x = 5;
        int y = 8;
        int z = 3;
     
        int & max = VariableMaximum (x,y,z);
        max = max + 10;
     
        std::cout << "Score de X : " << x << std::endl;
        std::cout << "Score de Y : " << y << std::endl;
        std::cout << "Score de Z : " << z << std::endl;
     
        return 0;
    }

    Code Shell : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ g++ score.c++ -o score
    $ ./score
    Score de X : 5
    Score de Y : 18
    Score de Z : 3

    La fonction VariableMaximum() sert à déterminer laquelle des trois variables passées en argument est la plus grande. Dans cet exemple, il y a transitivité des références : je pars de trois variables locales, je les passe par référence à la fonction, la fonction me renvoie une référence vers la plus grande. On peut donc considérer, au point de vue de la conception, qu'il me renvoie « la variable elle-même » et non simplement sa valeur. Enfin, je déclare une référence nommée « max » vers une autre variable : celle-là même qui m'a été renvoyée par la fonction.

    À l'issue de ce petit tour, « max » est donc un alias de « x », de « y » ou de « z ». Tu peux également constater que mes « cout » qui suivent n'utilisent que ces trois variables. Jamais « max ».

    Tu peux également constater que le problème serait insoluble avec des variables globales, car ta fonction n'utiliserait toujours que les trois mêmes variables, d'une part, et ne pourrait jamais ne renvoyer que leur valeur.



    Bon, tu comprends aussi qu'à ce stade, ce n'est plus une explication, c'est un cours. Des concepts simples peuvent avoir des implications très tordues. C'est souvent le cas en mathématiques, et c'est quasiment toujours le cas avec le C++. Donc, à toi de te replonger dans tes bouquins, maintenant.

  7. #7
    Nouveau membre du Club
    Inscrit en
    Novembre 2008
    Messages
    90
    Détails du profil
    Informations forums :
    Inscription : Novembre 2008
    Messages : 90
    Points : 36
    Points
    36
    Par défaut
    merci bcp obsidian maintenant et gràce a votre derniere explication j j ai compris ce que veut dire référence en c++

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    À ton service, mais n'oublie pas .

    Bon courage.

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

Discussions similaires

  1. probleme avec les references
    Par Zorgz dans le forum API standards et tierces
    Réponses: 1
    Dernier message: 16/02/2007, 11h58
  2. renvoyez les references d une cellule
    Par chamus dans le forum Macros et VBA Excel
    Réponses: 5
    Dernier message: 27/12/2006, 16h43
  3. je comprend pas les reference
    Par killer_instinct dans le forum C++
    Réponses: 13
    Dernier message: 08/12/2006, 19h49
  4. Problème avec les references
    Par Floyd dans le forum Langage
    Réponses: 5
    Dernier message: 04/05/2006, 14h25
  5. URL dans les références bibliographiques
    Par subzero82 dans le forum Bibliographies - Index - Glossaires
    Réponses: 1
    Dernier message: 26/03/2006, 19h09

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