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 :

pointeur et reference


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Octobre 2009
    Messages
    48
    Détails du profil
    Informations forums :
    Inscription : Octobre 2009
    Messages : 48
    Par défaut pointeur et reference
    Bonjour voila je suis novice en C++ et le chapitre sur les pointeur et les référence m'embrouille l'esprit!
    J'explique mon problème:

    un pointeur contient l'adresse d'un autre objet,
    les référence permettent de récupérer l'adresse d'un objet

    mais je ne comprend pas l'exemple suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    int i=0;      /* Déclare une variable entière. */
    int *pi;      /* Déclare un pointeur sur un entier. */
    pi=&i;        /* Initialise le pointeur avec l'adresse de cette
                    variable. */
    *pi = *pi+1;  /* Effectue un calcul sur la variable pointée par pi,
                     c'est-à-dire sur i lui-même, puisque pi contient
                     l'adresse de i. */
     
                  /* À ce stade, i ne vaut plus 0, mais 1. */
    donc cet exemple a quoi correspond pi?

    et que signifie:


    int i=0;
    int *pi=&i;
    *pi=*pi+1;

    dans cet exemple i vaut 1 mais on a dit que le pointeur *pi contenait l'adresse de i mais l'adresse de i ne vaut pas 0 non?

  2. #2
    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,

    Attention, tu te trompes déjà:

    Un pointeur représente, effectivement, l'adresse à laquelle on trouvera une variable, mais une référence est... l'alias d'une variable.

    Il y a deux différences principales entre un pointeur et une référence:
    1. Une référence assure l'existence de la variable référencée, alors qu'un pointeur peut ne pointer sur rien
    2. Une référence assure plus facilement la constante de la variable référencée qu'un pointeur

    Ta confusion vient du fait que les symboles utilisés pour déclarer une référence et celui de l'opérateur "address of" (qui permet de récupérer l'adresse d'une variable) sont identiques.

    Pour te permettre de faire la différence entre les deux, tu peux te dire que l'esperluette ' & ' est:
    • utilisée pour représenter une référence lorsqu'elle est utilisée pour une déclaration (de variable ou d'argument). Elle est donc précédée d'un nom de type et d'un "CV-qualifier" éventuel et suivie (ou non) du nom de la variable ou de l'argument
    • utilisée pour représenter l'opérateur "address of" lorsqu'elle est utilisée dans le cadre d'une affectation ou du passage... de l'adresse d'une variable comme argument. Elle apparait donc soit juste après un symbole d'égalité soit dans un appel de fonction.
    Pour que tu puisse comprendre, voici quelques lignes de code, et les explications qui vont bien.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Type var; // déclaration d'une variable
    Type * ptr; // déclaration d'un pointeur du même type que la variable 
    // l' & est précédé d'un signe = : c'est l'opérateur address of
    ptr = & var;
    // l'& est dans la partie "déclaration" : c'est une référence
    Type & ref = var; 
    // l'& est précédée du signe = : c'est l'opéateur address of
    if(ptr== & var) 
    // une déclaration de fonction (ou sa signature): c'est une référence
    void foo(Type /* const */ & /* laref */);
    // on est dans le cadre d'un appel de fonction: c'est l'opérateur address of
    bar(&var);
    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

  3. #3
    Membre Expert
    Homme Profil pro
    Chercheur
    Inscrit en
    Mars 2010
    Messages
    1 218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Chercheur

    Informations forums :
    Inscription : Mars 2010
    Messages : 1 218
    Par défaut
    Bonjour,

    Citation Envoyé par hostyle Voir le message
    donc cet exemple a quoi correspond pi?
    Dans ton exemple, pi représente un "pointeur sur int".

    Citation Envoyé par hostyle Voir le message
    et que signifie:

    int i=0;
    int *pi=&i;
    *pi=*pi+1;
    Cela signifie que pi va "pointer" sur i.
    Il y a une petite subtilité à la dernière ligne : une fois un pointeur déclaré, on utilise l'opérateur * pour accéder à l'adresse vers laquelle il pointe.
    Ainsi, à la ligne
    on accède à l'adresse vers laquelle pointe pi, c'est-à-dire celle de i, et on procède à une bête incrémentation (i=i+1).

    C'est la raison pour laquelle i vaut 1 à la fin.

  4. #4
    Membre actif Avatar de Chessmaster1966
    Inscrit en
    Juillet 2010
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Juillet 2010
    Messages : 63
    Par défaut
    Comme l'a dit Koala01 Il ne faut pas confondre :
    1) &, représente l'opérateur d'adressage c'est à dire qu'il retourne l'adresse de la variable qu'il a en operande (&i)
    2) & sert également à créer un alias. Un alias c'est tout simplement un autre nom pour une variable (en quelque sorte un surnom).

    Donc dans l'exemple que tu as donné :


    int i = 0;
    Ce "statement" défini un objet mémoire initialisé à la valeur 0 et portant le nom de i.

    int *pi = &i;
    Ce "statement" défini un objet mémoire initialisé avec l'adresse mémoire de l'objet i et porte le nom pi.

    L'étoile est l'opérateur de déréférencement mais ici dans ce "statement" il sert à définir un pointeur.

    Donc, dans ce "statement" le compilateur va d'abort récupérer l'adresse de l'objet i puis l'a placer dans l'objet pi.

    A ce stade le pointeur pi ne contient pas la valeur 0 mais l'adresse de la variable i. Pour pouvoir manipuler la valeur de i via le pointeur pi il faut utiliser l'opérateur de déréférencement (*) de la façon que tu as faite :
    *pi = *pi + 1 équivaut à ++i.

    Si tu n'utilise pas l'opérateur de déréférencement comme ceci :
    pi = pi + 1
    alors tu passe à l'adresse suivante donc pi pointe sur n'importe quoi et te causera bien des soucis.

    Pour l'alias c'est une toute autre histoire.
    Une variable qui est un alias d'un autre objet est un surnom et doit obligatoirement être initialiser au moment ou l'on le déclare.
    Attention ce n'est pas vraiment une variable mais un autre nom qui se déclare comme une variable.

    int i = 1200;
    int &ai = i;

    ai = 2000; //Equivaut à i = 2000, on utilise son surnom (ai n'est pas un objet mémoire à part entière mais l'objet mémoire nommé i).

    Comme tu peux le voir ce n'est pas la même chose.

    Conclusion :
    1) un pointeur ne se déclare pas comme un alias et inversement.
    2) un pointeur peut pointer sur n'importe quel objet mémoire ce n'est pas le cas pour un alias.
    3) un pointeur peut être simplement déclarer sans être initialisé alors qu'un alias ne le peut pas.

    Il faut si possible utiliser des alias plutôt que des pointeurs quand cela est possible. Les alias
    présentent bien plus de sécurité qu'un pointeur.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    230
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 230
    Par défaut
    Bonjour à tous,

    je ressors ce topic car moi aussi j'ai du mal à me représenter la différence concrète qu'il y a entre une référence et un pointeur.

    Par exemple le code ci dessous :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void fonction(int i, std::string s, Objet *o) {
       //bla bla bla
    }
     
    void main() {
        int a = 0;
        std::string t = "ma string;"
        Objet *p = new Objet;
    }
    Si j'ai bien compris l'avantage de la référence sur le pointeur c'est que la référence permettrait d'avoir la certitude que l'adresse vaut quelque chose de cohérent. Par contre laquelle des 2 syntaxes est une référence :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Objet o;
    Objet & o;
    Pourquoi dans certains cas (QT par exemple) les objets sont initialisés comme ceci :
    Est-ce que cela correspond à une valeur, un pointeur ou une référence... ou autre ?

    Enfin (pour le moment), jusqu'à présent j'écris mes fonctions pour qu'elles recoivent un pointeur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void fonction(Objet *o);
    quel avantage il y aurait à écrire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    void fonction(Objet & o);
    ?

    Ca doit vous sembler bateau comme question mais toutes ces syntaxes différentes rendent selon moi le langage confus et les explications et cours trouvés sur internet le sont encore plus...

    Merci
    Tristan

  6. #6
    Membre très actif Avatar de Firwen
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    472
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2009
    Messages : 472
    Par défaut
    Est-ce que cela correspond à une valeur, un pointeur ou une référence... ou autre ?
    Techniquement une chaine de caractere constante comme dans ton example : "test" est un "const char *".

    Ceci dit, dans le cas de Qt, c'est un peu particulier. Certaines methodes exigent un type QString qui est automatiquement construit à partir de ton "const char *" http://qt.developpez.com/doc/latest/qstring.html

    quel avantage il y aurait à écrire :
    Code :


    void fonction(Objet & o);


    ?
    ça apporte entre autres une certaine sureté de typage.

    Lorsque l'on passe une variable par pointeur, si le pointeur passé est nul ou qu'il n'est pas initialisé, des comportements non-souhaités arrivent.
    Généralement, un magnifique SEGfault qui blesse profondemment ton égo

    Lorsque l'on passe une variable par reference, ces problèmes ne se posent pas ( dans la théorie :p )

  7. #7
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    Le problème de la définition "alias", c'est qu'on peut presque la jeter par la fenêtre dès qu'une référence est en paramètre de fonction; à ce moment là, c'est peu de chose de plus (mais un peu quand même) qu'un pointeur déguisé.

    Mais il reste certaines choses que les références assurent:
    Une référence n'est jamais nulle tant qu'on ne joue pas avec des pointeurs autour. Tu n'as pas à tester la nullité d'une référence; tu peux, au pire, mettre un assert() dessus et c'est tout, et si l'assertion pète, c'est le maniement des pointeurs qu'il faut corriger, jamais la référence elle-même.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

Discussions similaires

  1. Pointeurs et reference : besoin de precisions
    Par gangsoleil dans le forum Débuter
    Réponses: 10
    Dernier message: 25/07/2012, 14h45
  2. Différence entre Pointeurs et References
    Par Le Pharaon dans le forum C++
    Réponses: 43
    Dernier message: 17/10/2011, 13h47
  3. Passage de tableau de pointeur par reference
    Par dahtah dans le forum Débuter
    Réponses: 7
    Dernier message: 25/08/2011, 17h13
  4. Pointeur et reference
    Par SofEvans dans le forum Débuter
    Réponses: 12
    Dernier message: 20/07/2009, 17h30
  5. Réponses: 3
    Dernier message: 06/07/2007, 14h54

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