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

  1. #1
    Membre à l'essai
    Inscrit en
    Octobre 2009
    Messages
    48
    Détails du profil
    Informations forums :
    Inscription : Octobre 2009
    Messages : 48
    Points : 18
    Points
    18
    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 sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    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 expérimenté
    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
    Points : 1 685
    Points
    1 685
    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 régulier Avatar de Chessmaster1966
    Inscrit en
    Juillet 2010
    Messages
    63
    Détails du profil
    Informations forums :
    Inscription : Juillet 2010
    Messages : 63
    Points : 74
    Points
    74
    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.
    Le bonheur est sans raison

  5. #5
    Membre habitué
    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
    Points : 132
    Points
    132
    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 expérimenté 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
    Points : 1 587
    Points
    1 587
    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 )
    It's not a bug, it's a feature

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    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.

  8. #8
    Membre habitué
    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
    Points : 132
    Points
    132
    Par défaut
    Ok je comprends ce que tu veux dire, mais pardonne moi ça reste toujours aussi flou surtout pour la transmission de mon pointeur de fonctions en fonctions.

    Je vais mettre un bout de code et si tu veux bien tu as me le traduire en version avec référence. (J'ai décomposé les lignes pour voir les valeurs de retour supposées etc...

    Code : 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
     
    void fonction(Objet *obj, int a) {
        std::string str = obj->operation();
     
        if(str == "resultat")
            cout << "C'est bon" << endl;
     
     
    }
     
    void main() {
        Objet *ob = new Objet;
     
        fonction(ob);
        delete ob;
    }
    Si j'utilise la référence, est-ce que ca veut dire que je n'ai plus besoin de faire nulle part un delete ? Quelle est la conséquence au niveau mémoire.

    Surtout, où trouver un bon cours sur ce sujet ?
    Merci

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    La seule "version référence" ici, ne supprimera pas le pointeur.

    Par contre, en gardant les pointeurs, tu peux faire ceci:
    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
    void fonction(Objet *pobj, int a) {
        if(pobj == 0)
            throw std::exception("pointeur nul!");
     
        std::string str = iobj->operation();
     
        if(str == "resultat")
            cout << "C'est bon" << endl;
     
     
    }
     
    void main() {
        Objet ob;
     
        fonction(&ob);
    }
    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.

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Et ensuite, remplacer le pointeur par une référence:
    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
    void fonction(Objet &obj, int a) {
        std::string str = obj.operation();
     
        if(str == "resultat")
            cout << "C'est bon" << endl;
     
     
    }
     
    void main() {
        Objet ob;
     
        fonction(ob);
    }
    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.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    En fait, j'ai l'impression que la question devrait être "dans quel cas devrons nous utiliser un pointeur, et dans quel cas devrons nous utiliser une référence "

    Et la réponse serait alors "il n'y a que quelques cas dans lesquels il faut utiliser un pointeur."

    On peut citer:
    - Quand tu as une relation de contenant à contenu, et que tu veux que le contenu puisse se rappeler dans quel contenant il se trouve.

    Ce serait le cas de deux classes proches de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class Contenant
    {
        /*...*/
        private: 
            std::vector<Contenu> items;
    }:
    class Contenu
    {
        /* ...*/
        private:
            Contenant * holder;
    };
    - Quand tu veux créer toi-même un objet qui doit pouvoir être mis en relation avec un (ou plusieurs) objets de type identique, comme les itérateurs, les éléments de pile, de file, de liste, ... :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Element
    {
        /*...*/
        private:
            Element * next; 
            Element * previous;
            /* ce pourrait être */
            Element * lesser;
            Element * greater;
    };
    - Quand un objet peut ne pas exister. Il s'agira alors de veiller à initilialiser correctement le pointeur à une valeur connue comme représentant un objet inexistant et de vérifier l'existence de l'objet avant toute tentative d'utilisation de celui-ci
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    void foo()
    {
        Objet * ptr=NULL;
        if(ptr /* != NULL */)
       {
           /* l'objet existe */
       }
    }
    - Quand tu a besoin d'un objet polymorphe et que tu ne sais pas à la base quel sera le type réel:
    Code : 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
     
    class Base
    {
        public:
            virtual ~Base();
    };
    class D1 : public Base
    { 
    };
    class D2 : public Base
    {
    };
    void foo()
    {
        Base * ptr=NULL;
        /* une logique permettant de déterminer si on a besoin de D1 ou de
         * D2
         */
        if( choix==1)
            ptr = new D1;
        else
            ptr = new D2;
        ptr->doSomething(); // invocation du comportement polymorphe
        delete ptr; // ne pas oublier la libération de la mémoire
                    // quand on n'a plus besoin de l'objet
    }
    - Il n'est pas exclu que j'oublie une ou l'autre situation ...

    Dans tous les autres, il est préférable d'utiliser une référence, en veillant les passer sous forme "const correct" (transmettre une référence constante si la fonction ne peut pas modifier le paramètre transmis)
    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

  12. #12
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 418
    Points : 1 658
    Points
    1 658
    Par défaut
    Je connais très très peu C++ mais je m’intéresse à ces questions et j’ai besoin d’une précision.



    J’ai compris que les pointeurs et les références contiennent des adresses.
    Là dessus, je ne pense pas faire d’erreur.

    Mais:

    1)
    Les pointeurs sont ils des variables et exclusivement des variables ?
    Les références sont elles des variables et exclusivement des variables ?
    C’est à dire JAMAIS des objets.

    2)
    Les adresses contenues dans les pointeurs et les références sont elles toujours des adresses d’autres variables ou peuvent elles être celles d’objets ?


    Le mot objet étant ici pris dans le sens précis de “instance d’une classe“ et non pas au sens vague de “entité qui se balade dans la mémoire vive“.

    Merci

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par eyquem Voir le message
    Je connais très très peu C++ mais je m’intéresse à ces questions et j’ai besoin d’une précision.



    J’ai compris que les pointeurs et les références contiennent des adresses.
    Là dessus, je ne pense pas faire d’erreur.
    Justement, non, du moins, pas du point de vue du langage lui-même (on observera effectivement une similitude au niveau du binaire généré, mais on sort alors du domaine du langage )


    Mais:

    1)
    Les pointeurs sont ils des variables et exclusivement des variables ?
    Oui.

    Ce sont des variables numériques particulières en cela qu'elles contiennent... l'adresse mémoire à laquelle on trouvera effectivement l'objet pointé.
    Les références sont elles des variables et exclusivement des variables ?
    C’est à dire JAMAIS des objets.
    Ce ne sont même pas des variables: ce ne sont que des identifiants (comprend: quelque chose que l'on identifie de manière unique dans la portée envisagée).

    Ce ne sont que "d'autres noms" donnés à une seule et même variable. C'est pour cela que le terme "alias" revient régulièrement

    Nous pourrions faire le parallèle avec Spiderman et Peter Parker: ce sont deux noms représentant exactement la même personne et ce qui arrive à Spideerman arrive en réalité à ... Peter Parker.

    2)
    Les adresses contenues dans les pointeurs et les références sont elles toujours des adresses d’autres variables ou peuvent elles être celles d’objets ?
    En fait, une référence ne contient, comme je te l'ai fait remarquer, absolument pas l'adresse de l'objet référencé.

    Ce n'est qu'un autre nom pour l'objet référencé

    Maintenant, comme un pointeur est une variable en tant que telle, il est tout à fait possible... de récupérer l'adresse mémoire à laquelle cette variable se trouve.

    On arrive alors au concept des "pointeurs de pointeurs", avec tout ce que cela sous-entend.

    Par contre, une référence n'a pas d'existence propre en mémoire: c'est l'objet référencé qui existe réellement

    On ne peut donc pas récupérer l'adresse de la référence et, comme il n'existe aucun moyen de différencier l'objet référencé de la référence, on ne peut donc pas... récupérer l'adresse de l'objet.

    Par contre, il est tout à fait possible de déclarer une référence sur un pointeur, vu que le pointeur est une variable
    Le mot objet étant ici pris dans le sens précis de “instance d’une classe“ et non pas au sens vague de “entité qui se balade dans la mémoire vive“.

    Merci
    Ni les pointeurs ni les références ne seront jamais des objets.

    Lorsque l'on parle de "pointeur" ou de "référence", sans précision, on fait en réalité un abus de langage, car il faudrait en réalité parler de "pointeur sur objet" ou de "référence vers objet / vers variable"
    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

  14. #14
    Membre actif

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Points : 206
    Points
    206
    Par défaut
    Personnellement, je n'ai jamais compris pourquoi la plupart des gens sont "contre les pointeurs" (peut être parce que j'ai commencé en C avant C++?).

    En tout cas, aujourd'hui j'utilise les références quand :

    -J'ai une fonction et je veux pouvoir modifier la variable passée en paramètre.
    -J'ai une fonction et sizeof(variable)>sizeof(void*). La référence ici sert à éviter la copie.

    Dans tous les autres cas, il faut utiliser des pointeurs ou pointeurs intelligents :

    -Pour substitué un type dérivé en type de base (afin de les mettre dans un conteneur).
    -Pour faire un tableaux de taille statique (et alloué sur le tas) sans utiliser boost.array
    -Pour laisser l'option de passer NULL en argument (il faut tout de même préférer la surcharge de fonction dans la majorité des cas).
    -...

    Le gros avantage du pointeur (sur la référence) : Tu peux plus facilement comprendre ce qui se passe.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    Personnellement, je n'ai jamais compris pourquoi la plupart des gens sont "contre les pointeurs" (peut être parce que j'ai commencé en C avant C++?).
    Il ne s'agit pas d'être "contre les pointeurs", il s'agit de ne les utiliser que dans des cas clairement déterminés, dans lesquels leur utilisation devient absolument indispensable (et de les éviter chaque foisque possible

    En tout cas, aujourd'hui j'utilise les références quand :

    -J'ai une fonction et je veux pouvoir modifier la variable passée en paramètre.
    -J'ai une fonction et sizeof(variable)>sizeof(void*). La référence ici sert à éviter la copie.
    Le problème, c'est que tu ne peux absolument pas faire respecter la constance au départ d'un pointeur.

    Or, le principe de la "const correctness" apporte une série d'avantages non négligeables en t'interdisant toute modification inopportune.

    Dans tous les autres cas, il faut utiliser des pointeurs ou pointeurs intelligents :
    Les pointeurs intelligents, oui...

    Les pointeurs "bruts" très rarement (sauf éventuellement en interne)

    -Pour substitué un type dérivé en type de base (afin de les mettre dans un conteneur).
    Un pointeur intelligent sera surement bien plus pratique et sécuritaire à utiliser qu'un pointeur brut dans ce cas particulier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    -Pour faire un tableaux de taille statique (et alloué sur le tas) sans utiliser boost.array
    L'avantage de la classe array est qu'elle fournit la possibilité d'utiliser un iterateur, et donc d'utiliser une interface qui te permet de cacher complètement le fait que tu manipule un tableau
    -Pour laisser l'option de passer NULL en argument (il faut tout de même préférer la surcharge de fonction dans la majorité des cas).
    Effectivement, si un argument peut ne pas exister, l'utilisation d'un pointeur sera préférable, mais l'utilisation d'un pointeur intelligent reste encore une fois plus sécuritaire
    Le gros avantage du pointeur (sur la référence) : Tu peux plus facilement comprendre ce qui se passe.
    Tu peux au contraire comprendre bien plus facilement ce qui se passe avec une référence qu'avec un poitneur.

    Car il te suffit de te rendre compte qu'une référence est constante pour savoir que l'argument que tu passe lors de l'appel de la fonction ne sera pas modifié, alors que seul le code de la fonction appelée peut te permettre de faire cette vérification lorsque tu transmet un pointeur
    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

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Le problème, c'est que tu ne peux absolument pas faire respecter la constance au départ d'un pointeur.
    Que veux-tu dire par là?
    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.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Que veux-tu dire par là?
    J'aurais du dire "tu as beaucoup plus difficile à faire respecter la const-correctness avec les pointeurs".

    Ne serait-ce que parce ce que type const *, type * const et type const * const représentent trois situation totalement différentes:

    Avec les références constantes, il n'y a aucune ambigüité possible: tu ne peux appeler que les fonctions qui se sont engagées à ne pas modifier l'objet courent.

    Avec les pointeurs, la présence du mot clé const ne te donne pas le même genre de certitude: type * const t'empêche de faire pointer le pointeur sur une autre adresse mémoire, mais n'interdit absolument pas de modifier l'objet pointé

    De plus, les références constantes ont l'énorme avantage de permettre la création d'une variable temporaire anonyme quand l'objet doit exister (ne serait-ce que dans la fonction appelée) tout en évitant les copies inutiles si on transmet effectivement un objet existant dans la fonction appelante.
    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

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