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 :

Références et pointeurs


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 69
    Par défaut Références et pointeurs
    Bonsoir à vous, j'ai vu plusieurs sujets parlant de ça mais j'avoue c'est toujours pas clair pour moi, je vois le principe des pointeurs et références mais je comprends vraiment pas dans quel cas c'est utile, si une personne voulait bien me montrer ce qu'on peut faire et qui est impossible sans référence par exemple, ce serait parfait pour moi, merci à vous.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 152
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 152
    Billets dans le blog
    4
    Par défaut
    Une référence est un allias sur une variable, tu peux par exemple faire auto& toto = tata ? toto1 : toto2; et paf toto permettra de travailler avec toto1 ou toto2 par la suite selon une condition.
    Un pointeur c'est un peu identique, mais il peut avoir la valeur particulière nullptr (ou NULL dans les versions précédentes), ça permet d'avoir une valeur optionnelle, par exemple en paramètre out de fonction : tu peux mettre une référence, dans ce cas elle est obligatoire, ou un pointeur, qui permet de passer la valeur nullptr (voire peut prendre nullptr par défaut) si l'on se moque de récupérer cette valeur.
    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
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Un exemple très simple d'utilisation des références, avec un usage nécessaire, c'est la fonction qui échange les valeurs de deux variables. (std::swap)

    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
    #include <iostream>
     
    void swap(int& a, int& b) {
        int temp = a;
        a = b;
        b = temp;
    }
     
    int main() {
        int var1 = 1;
        int var2 = 2;
     
        std::cout << "valeur des variables: " << var1 << " et " << var2 << std::endl;
        swap(var1, var2);
        std::cout << "valeur des variables: " << var1 << " et " << var2 << std::endl;
     
        return 0;
    }
    Dans ce programme, swap prend en argument deux références.
    Lorsqu'elle est appelée, ses deux paramètres sont initialisés avec var1 et var2, donc a et b en sont des alias.
    À la fin de l'appel, les variables qui ont été aliasées sont bien échangées.

    Cela dit, l'usage principale de la référence, c'est les "références constantes", telles que Bidule const& bidule.
    Ceci déclare une référence sur une valeur (non modifiable) de type Bidule.
    Étant une référence, elle prend probablement beaucoup moins de mémoire que l'objet Bidule qu'elle désigne, qu'on évite de copier, ce qui peut être lourd en mémoire, lent, voire tout simplement impossible.
    C'est extrèmement efficace pour les arguments de fonction, et pour tout les types non primitifs.

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

    Il faut peut-être commencer par savoir ce qu'est un pointeur et une référence.

    Un pointeur, c'est une valeur numérique entière (généralement) non signée -- comme short,int ou long -- qui représente l'adresse mémoire à laquelle se trouve (ou, plutôt : devrait se trouver) la donnée que l'on veut manipuler.

    C'est chiant d'utiliser les pointeurs, pour plusieurs raisons:

    D'abord, parce que, comme pour toutes les valeurs numériques, il est possible de les copier: si ptrA représente l'adresse mémoire à laquelle nous allons trouver une donnée de type Type, nous pouvons très bien écrire un code proche de Type * ptrB = ptrA;, (ou mieux, depuis C++11 : auto * ptrB = ptrA;) qui aura pour résultat de faire que ptrB représentera exactement la même adresse mémoire que celle représentée par ptrA, mais qui ne sera pas mise automatiquement à jour par la suite.

    Ensuite -- et je vais apporter une explication à ce que je viens de dire par la même occasion -- les pointeurs sont généralement associés à l'allocation dynamique de la mémoire. Mais, si on demande de l'espace mémoire au système d'exploitation, il faut bien la lui rendre à un moment ou à un autre. Et donc, l'adresse mémoire représentée par un pointeur peut tout à fait correspondre à une adresse mémoire qui a déjà été rendue au système d'exploitation. Ce n'est pas parce que l'on fera un delete ptrA que ptrA sera mis à jour... Et encore moins que ptrB le sera.

    Or, si on essaye d'accéder à ce qui se trouve à une adresse mémoire qui a déjà été rendue au système d'exploitation, cela va mal se passer car nous aurons ce que l'on appelle une erreur de segmentation, et l'application va planter. C'est la raison pour laquelle on insiste généralement très fort sur le fait de redéfinir la valeur des pointeurs à nullptr(ou à NULL) quand on a rendu la mémoire au système d'exploitation: c'est parce que cette valeur correspond à une adresse mémoire que l'on sait être invalide (et donc, à laquelle il ne faut pas aller chipoter).

    Le truc, c'est que nullptr est la seule valeur que l'on soit en mesure de tester pour s'assurer de la validité d'un pointeur : s'il vaut nullptr, on a forcément affaire à un pointeur invalide. MAIS... ce n'est pas parce que le pointeur ne vaut pas nullptr que l'adresse mémoire qu'il représente est toujours "accessible" à notre application

    Je ne vais pas te faire, dans le cadre de cette intervention, le speach sur la difficulté qu'il y a à gérer l'allocation dynamique de la mémoire avec un langage à exceptions comme C++, car cela déborderait trop de l'explication (il reste malgré tout en stock, en cas de besoin ). Mais cette difficulté rajoute pas mal de complexité au passage

    Maintenant que nous avons (à peu près) fait le tour de ce qu'est un pointeur, intéressons nous à ce qu'est une référence. Comme l'a dit Bousk, une référence n'est qu'un alias de la donnée référencée. En gros, c'est le pseudonyme sous lequel nous pourrons connaître une donnée. Ce qui est chouette, c'est que tout ce que tu fais subir à une référence, tu le fais en réalité subir à la donnée référencée, un peu comme toute l'intervention écrite par ce type qu'est koala01 a en réalité été écrit par ... Moi, Philippe Dunski à l'état civil.

    Il existe deux grosses différences entre un pointeur et une référence:
    1. Une référence est forcément associée à une donnée. Un code proche de Type & ref; sera refusé par le compilateur, car l'association doit se faire directement, alors qu'un pointeur peut ne prendre aucune adresse dans un premier temps (même s'il n'est jamais prudent de le faire): un code proche de Type * ptr; sera tout à fait accepté.
    2. Une fois que la référence est définie (qu'elle fait référence à une donnée particulière), elle reste associée à cette donnée "pour toute sa vie" (quand je décéderai, le plus tard possible, je serai toujours "connu comme koala01" ) alors que l'on peut très bien changer l'adresse mémoire représentée par un pointeur et lui donner celle d'une donnée tout à fait différente

    Il faut enfin noter que la notion de référence vient avec certaines restrictions, comme le fait que l'on ne peut pas créer une collection de références : un code proche de std::vector<Type &> tab; sera purement et simplement refusé par le compilateur .

    Maintenant que tu as sans doute une idée bien plus claire de ce que sont les pointeurs et les références, il est temps de répondre à ta question: je comprends vraiment pas dans quel cas c'est utile?

    De manière générale, tu utiliseras une référence ou un pointeur à chaque fois que tu ne veux pas effectuer une copie de la donnée:
    • Parce que la copie d'une donnée est un processus assez lourd, aussi bien en temps d'exécution qu'en ressources nécessaires
    • Parce que tu ne veux surtout pas avoir, à un instant T de l'exécution de ton programme, deux données qui auraient exactement les mêmes valeurs
    • Pour plein d'autres raisons encore qui reviendront sans doute au final aux deux premières

    Mais la véritable question à se poser serait plutôt
    Quand dois-je utiliser une référence et quand dois-je utiliser un pointeur
    La réponse à cette question est "relativement simple", même si elle fait un peut "réponse de breton". Je te l'ai dit en début d'intervention: les pointeurs, c'est chiant à manipuler. Et toute la réponse va être orienté par cette constatation. La voici:

    Utilises les références à chaque fois que faire se peut et n'utilises les pointeurs que si tu n'as vraiment pas le choix.
    Il te faudra sans doute quelques temps pour comprendre à quoi correspondent ces deux situations, mais, en gros, l'idée c'est que, lorsque tu te trouve dans une situation dans laquelle tu dois utiliser l'un des deux, ton "choix par défaut" soit d'utiliser les références, et que tu ne décides de te tourner vers l'utilisation de pointeur que parce que les références ne correspondent décidément pas à tes besoins
    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 confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 69
    Par défaut
    Merci beaucoup à vous pour toutes ces réponses détaillées, je serai toujours surpris quand des gens calés dans leurs domaines donnent de leur temps juste pour aider un inconnu, c'est peut-être ça la passion, ou encore les explications renforcent votre savoir, dans tout les cas j'y vois beaucoup plus clair à présent. Mais juste pour être sûr, vous avez tendances à préférer utiliser des références (ou pointeurs) plutôt que de créer plusieurs variables identiques dans un soucis de temps d'exécution ou d'espace mémoire occupé ?

  6. #6
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2009
    Messages
    4 493
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 493
    Billets dans le blog
    1
    Par défaut
    Mine de rien en aidant les gens tu progresses toi même Et puis d'autres nous ont aidé avant, on etait contents de les trouver !

    Il ne faut pas perdre de vue qu'en C++ les paramètres sont passés par copie. Quand tu passes à un objet à une fonction celle-ci ne travaille pas sur l'original. Si cette fonction doit modifier l'objet original alors qu'elle travaille sur une copie, il faudrait qu'elle retourne ce nouvel objet pour à nouveau le copier dans l'original, qui sera enfin modifié... Au-delà des performances et de la mémoire consommée, ça parait quand même assez "débile" alors que tu pourrais passer un pointeur ou une référence (qui sera aussi copié mais pas grave on peut toujours accéder à la variable originale !).

  7. #7
    Membre confirmé
    Homme Profil pro
    Étudiant
    Inscrit en
    Mars 2018
    Messages
    69
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2018
    Messages : 69
    Par défaut
    Me voila éclairé, merci à vous, sujet résolu

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

Discussions similaires

  1. Compteur de référence et pointeurs communs
    Par Montor dans le forum Contribuez
    Réponses: 2
    Dernier message: 04/12/2009, 19h40
  2. référence ou pointeur
    Par storm_2000 dans le forum Débuter
    Réponses: 1
    Dernier message: 11/10/2009, 20h57
  3. Réponses: 2
    Dernier message: 30/08/2009, 10h55
  4. Différence entre référence et pointeur ?
    Par Vivian Pennel dans le forum Langage
    Réponses: 3
    Dernier message: 03/08/2007, 17h19
  5. Références et pointeurs sur un tableau
    Par smag dans le forum C++
    Réponses: 2
    Dernier message: 01/03/2005, 20h29

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