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

Langage C++ Discussion :

Passage par référence d'un pointeur


Sujet :

Langage C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti Avatar de CaptainKrabs
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2018
    Messages : 25
    Par défaut Passage par référence d'un pointeur
    Bonjour,

    Je suis en train d'écrire un programme pour tester et comprendre différentes manières de passer des arguments à des fonctions.
    L'une d'entre elles consiste à passer en argument une référence de pointeur.

    Voici mon code :

    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
     
    #include <iostream>
     
    // Passage par pointeur
    void fctn1(int* arg1)
    {
    	(*arg1)++;
    	// *arg1 = *arg1 + 1;
    }
     
    // Passage par référence
    void fctn2(int& arg2)
    {
    	arg2++;
    }
     
    // passage par référence d'un pointeur
    void fctn3(int*& arg3)
    {
    	int tab[] = {4, 5, 6};
    	std::cout << "*tab = " << *tab << "\n";
    	arg3 = tab;
    	std::cout << "*arg3 = " << *arg3 << "\n";
    }
     
    // Passage d'un pointeur de pointeur (plutôt en C)
    void fctn4(int** arg4)
    {}
     
    // Affiche tableau
    void display_tab(const int* tab, const int size)
    {
    	for(int i = 0 ; i < size ; i++)
    		std::cout << tab[i] << "\t";
    	std::cout << "\n";
    }
     
    int main()
    {
    	int arg1 = 6;
    	std::cout << "arg1 = " << arg1 << " \n";
     
     
    	std::cout << "Appel fctn1 : passage par pointeur \n";
    	int* ptr_arg1 = &arg1;
    	fctn1(ptr_arg1);
    	std::cout << "arg1 = " << arg1 << " \n";
     
    	std::cout << "Appel fctn2 : passage par référence \n";
    	fctn2(arg1);
    	std::cout << "arg1 = " << arg1 << " \n";
     
    	std::cout << "Appel fctn3 : passage par référence d'un pointeur \n";
    	int tab[] = {7, 8, 9};
    	int* k = tab;
     
    	display_tab(k, 3);
    	fctn3(k);
    	std::cout << "*k = " << *k << "\n";
    	display_tab(k, 3);
     
     
    	std::cout << "Appel fctn4 : passage par pointeur d'un pointeur \n";
    	return 0;
    }
    J'ai cru comprendre qu'avec ce genre de méthode, on pouvait initialement déclarer un pointeur sur un tableau et modifier dans la fonction le pointeur afin qu'il pointe sur un nouveau tableau.

    Mon code compile mais je ne comprends pas les sorties consoles que voici :

    Nom : passage_arguments.png
Affichages : 124
Taille : 16,7 Ko

    En effet à l'intérieur de ma fonction fctn3 je comprends les différents "prints" que j'obtiens et mon pointeur pointe bien vers le premier élément du tableau.

    Cependant dès que je sors de la fonction, j'ai l'impression que le pointeur pointe vers ailleurs... et idem pour les autres valeurs ...
    Et ça comme si la "bonne référence" n'avait pas été transmise lors de la sortie de la fonction.

    Pouvez-vous m'expliquez pourquoi s'il vous plaît ?

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 766
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 766
    Par défaut
    ton problème: l'adresse d'une variable locale

    et quelques micro détails: ++arg2 (pas le seul) est mieux mais avec le temps le compilateur doit optimiser arg2++ (non création d'1 temporaire), std::endl au lieu de "\n" et sûrement const int const* tab (le pointeur aussi constant)

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Quand tu écris la ligne:
    Comme arg3 est une référence, tu es bien entrain de modifier la variable k. Mais la valeur tab que tu lui affectes c'est l'adresse d'une variable locale.
    Et donc à la sortie de la fonction ton pointeur k pointe sur une variable (le tableau tab) qui n'existe plus!

  4. #4
    Membre averti Avatar de CaptainKrabs
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2018
    Messages : 25
    Par défaut
    Citation Envoyé par foetus Voir le message
    ton problème: l'adresse d'une variable locale

    et quelques micro détails: ++arg2 (pas le seul) est mieux mais avec le temps le compilateur doit optimiser arg2++ (non création d'1 temporaire), std::endl au lieu de "\n" et sûrement const int const* tab (le pointeur aussi constant)
    Merci pour ces réponses, j'ai pu modifier mon programme que voici :
    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
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    #include <iostream>
     
    int TAB0[] = {1, 2, 3};
    int TAB[] = {4, 5, 6};
     
     
    // Passage par pointeur
    void fctn1(int* arg1)
    {
    	(*arg1)++;
    	// *arg1 = *arg1 + 1;
    }
     
    // Passage par référence
    void fctn2(int& arg2)
    {
    	++arg2;
    }
     
    // passage par référence d'un pointeur
    void fctn3(int*& arg3)
    {
    	arg3 = TAB;
    }
     
     
    // Passage d'un pointeur de pointeur (plutôt en C)
    void fctn4(int** var)
    {
        *var = TAB0;
    }
     
    // Affiche tableau
    void display_tab(const int* const tab, const int size)
    {
    	for(int i = 0 ; i < size ; ++i)
    		std::cout << tab[i] << "\t";
    	std::cout << std::endl;
    }
     
    int main()
    {
    	int arg1 = 6;
    	std::cout << "arg1 = " << arg1 << std::endl;
     
     
    	std::cout << "Appel fctn1 : passage par pointeur" << std::endl;
    	int* ptr_arg1 = &arg1;
    	fctn1(ptr_arg1);
    	std::cout << "arg1 = " << arg1 << std::endl;
     
    	std::cout << "Appel fctn2 : passage par référence" << std::endl;
    	fctn2(arg1);
    	std::cout << "arg1 = " << arg1 << std::endl;
     
    	std::cout << "Appel fctn3 : passage par référence d'un pointeur" << std::endl;
    	int tab[] = {7, 8, 9};
    	int* k = tab;
    	display_tab(k, 3);
    	fctn3(k);
    	display_tab(k, 3);
     
     
    	std::cout << "Appel fctn4 : passage par pointeur d'un pointeur" << std::endl;
        int brd[] = {7, 8, 9};
        int* ptr_brd;
        int** ptr2_brd;
     
        ptr_brd = brd;
        ptr2_brd = &ptr_brd;
        for(int i = 0 ; i < 3 ; ++i)    
            std::cout << (**ptr2_brd)++ << "\t";
        std::cout << std::endl;
        display_tab(*ptr2_brd, 3);
     
        fctn4(ptr2_brd);
     
        for(int i = 0 ; i < 3 ; ++i)    
            std::cout << (**ptr2_brd)++ << "\t";
        std::cout << std::endl;
        display_tab(*ptr2_brd, 3);
     
    	return 0;
    }
    Cependant, j'ai encore 2 interrogations :
    - Pourquoi est-il préférable d'utiliser std::endl au lieu de \n

    - Voici la sortie console que j'obtiens en exécutant mon code :
    Nom : passage_arguments2.png
Affichages : 84
Taille : 15,8 Ko

    Je ne comprends pas pourquoi l'affichage obtenu n'est pas le même en passant par la fonction display_tab (seul le premier élément du tableau change ...)?

    En vous remerciant par avance.

  5. #5
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Citation Envoyé par CaptainKrabs Voir le message
    Pourquoi est-il préférable d'utiliser std::endl au lieu de \n
    Quand avec std::cout tu transmets un message à la console, pour que le message soit visible, il doit être "flushé".
    Certaines bibliothèques effectuent automatiquement ce "flush" dès qu'un \n est émis, ton code t'apparait correct car la bibliothèque que tu utilises fait cela. En C++ standard il te faut ajouter << std::flush en dernier objet à transmettre. La fonction std::endl est équivalent à concaténation de << "\n" << std::flush. D'où il est souvent préférable d'utiliser std::endl au lieu d'un \n.
    Citation Envoyé par CaptainKrabs Voir le message
    Je ne comprends pas pourquoi l'affichage obtenu n'est pas le même en passant par la fonction display_tab (seul le premier élément du tableau change ...)?
    Parce que tu as incrémenté 3 fois la valeurs du premier élément de ton tableau (7 est devenu 10) pendant la séquence:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        for(int i = 0 ; i < 3 ; ++i)    
            std::cout << (**ptr2_brd)++ << "\t";  // le 1er élément est affiché et incrémenté!
    Ce que tu voulais faire, c'est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        auto  ptr = *ptr2_brd;     // variable intermédiaire nécessaire (sinon on modifierait *ptr2_brd dont à besoin le display() suivant
        for ( int i = 0 ; i < 3 ; ++i )    
            std::cout << *ptr++ << "\t";
    // ou bien
        for ( int i = 0 ; i < 3 ; ++i )    
            std::cout << (*ptr2_brd)[i] << "\t";

  6. #6
    Membre averti Avatar de CaptainKrabs
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2018
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2018
    Messages : 25
    Par défaut
    Citation Envoyé par dalfab Voir le message
    Quand avec std::cout tu transmets un message à la console, pour que le message soit visible, il doit être "flushé".
    Certaines bibliothèques effectuent automatiquement ce "flush" dès qu'un \n est émis, ton code t'apparait correct car la bibliothèque que tu utilises fait cela. En C++ standard il te faut ajouter << std::flush en dernier objet à transmettre. La fonction std::endl est équivalent à concaténation de << "\n" << std::flush. D'où il est souvent préférable d'utiliser std::endl au lieu d'un \n.

    Parce que tu as incrémenté 3 fois la valeurs du premier élément de ton tableau (7 est devenu 10) pendant la séquence:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        for(int i = 0 ; i < 3 ; ++i)    
            std::cout << (**ptr2_brd)++ << "\t";  // le 1er élément est affiché et incrémenté!
    Ce que tu voulais faire, c'est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
        auto  ptr = *ptr2_brd;     // variable intermédiaire nécessaire (sinon on modifierait *ptr2_brd dont à besoin le display() suivant
        for ( int i = 0 ; i < 3 ; ++i )    
            std::cout << *ptr++ << "\t";
    // ou bien
        for ( int i = 0 ; i < 3 ; ++i )    
            std::cout << (*ptr2_brd)[i] << "\t";

    D'accord, cela est plus clair pour moi.
    Merci beaucoup pour vos réponses

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

Discussions similaires

  1. Pointeurs et passage par référence
    Par stephan1609 dans le forum Débuter
    Réponses: 5
    Dernier message: 08/08/2012, 16h43
  2. Passage par référence versus par pointeur
    Par Seabast888 dans le forum Débuter
    Réponses: 14
    Dernier message: 14/09/2009, 18h17
  3. [pointeur][passage par référence] Perte des valeurs.
    Par ced600 dans le forum Débuter
    Réponses: 13
    Dernier message: 05/09/2008, 18h44
  4. Passage par référence/pointeur
    Par NiamorH dans le forum C++
    Réponses: 5
    Dernier message: 15/07/2008, 10h05
  5. Réponses: 10
    Dernier message: 27/06/2008, 14h16

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