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 :

[debutant(e)]passage par reference


Sujet :

C++

  1. #1
    Membre du Club
    Inscrit en
    Septembre 2006
    Messages
    86
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 86
    Points : 48
    Points
    48
    Par défaut [debutant(e)]passage par reference
    Bonjour tout le monde,


    J'ai lu dans le livre "penser en C++" que l'utilisation de passage par reference doit etre limite car ils ont des effets secondaires (Pass-by-reference semantics have side effects and should be used sparingly).


    1. quelles sont ses effets et est ce vrai de limiter leur utilisation ?


    Merci en avance

  2. #2
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Side-effect veut dire "effet de bord" là plutôt, ce qui veut dire que la fonction peut modifier l'objet qui lui est passé en argument, utilise des références constantes pour l'empêcher.

  3. #3
    r0d
    r0d est déconnecté
    Expert éminent

    Homme Profil pro
    tech lead c++ linux
    Inscrit en
    Août 2004
    Messages
    4 262
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : tech lead c++ linux

    Informations forums :
    Inscription : Août 2004
    Messages : 4 262
    Points : 6 680
    Points
    6 680
    Billets dans le blog
    2
    Par défaut
    Le sujet a été maintes fois discuté sur ce forum. Ce n'est pas que je n'ai pas envie de te répondre, mais c'est que ça va déboucher, comme d'habitude, sur un gros troll bien velu.

    La meilleure solution consiste à utiliser la fonctionnalité de recherche de ce forum
    « L'effort par lequel toute chose tend à persévérer dans son être n'est rien de plus que l'essence actuelle de cette chose. »
    Spinoza — Éthique III, Proposition VII

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

    D'abord, il semble intéressant de s'assurer que tu aies bien compris la différence entre le fait de passer un ojet par valeur et celui de passer un objet par référence.

    Quand tu crées des fonctions dont le prototype est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void FonctionVal(type obj);
    /* ou */
    void FonctionRef(type& obj);
    /* qui seraient utilisées sous une forme proche de */
     
    type mavar;
    FonctionVal(mavar);
    /*ou */
    FonctionRef(mavar);
    FonctionVal va travailler avec une copie de mavar, alors que FonctionRef va travailler avec mavar lui-meme.

    Du coup, si dans FonctionVal, tu modifie obj, mavar n'est pas modifiée une fois que la fonction a été appelée. Par contre, si tu modifie obj dans FonctionRef, les modification apportées seront répercutées sur mavar.

    Et c'est là que réside le principal effet de bord.

    On parle plus volontiers d' "effet de bord" que d' "effet secondaires" parce qu'un effet secondaire a cette connotation de "effet indésiré", alors qu'un effet de bord indique qu'il s'agit d'un comportement tout à fait cohérent avec la définition que l'on donne d'un terme, mais auquel on ne pensera pas forcément... avant de s'etre fait avoir

    Ceci étant dit, l'implémentation de ce que j'ai expliqué plus haut sous la forme de
    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
    #include <iostream>
     
    using namespace std;
    struct type
    {
        int x;
        int y;
    };
    void FonctionVal(type obj)
    {
        obj.x+=2;
        obj.y*=2;
        cout<<"2- Dans FonctionVal:"<<endl
            <<"    obj.x = "<<obj.x<<" obj.y = "<<obj.y<<endl<<endl;
    }
    void FonctionRef(type& obj)
    {
        obj.x*=2;
        obj.y+=2;
        cout<<"4- Dans FonctionRef:"<<endl
            <<"    obj.x = "<<obj.x<<" obj.y = "<<obj.y<<endl<<endl;
    }
    int main()
    {
        type mavar={10,10};
        cout<<"1- A la creation :"<<endl
            <<"    mavar.x = "<<mavar.x<<" mavar.y = "<<mavar.y<<endl<<endl;
        FonctionVal(mavar);
        cout<<"3- Apres FonctionVal"<<endl
        <<"    mavar.x = "<<mavar.x<<" mavar.y = "<<mavar.y<<endl<<endl;
        FonctionRef(mavar);
        cout<<"5- Apres FonctionRef:"<<endl
        <<"    mavar.x = "<<mavar.x<<" mavar.y = "<<mavar.y<<endl<<endl;
        return 0;
    }
    dont le code compile et fournit la sortie
    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
     
    1- A la creation:
        mavar.x = 10 mavar.y = 10
     
    2- Dans FonctionVal:
        obj.x = 12 obj.y = 20
     
    3- Apres FonctionVal:
        mavar.x = 10 mavar.y = 10
     
    4- Dans FonctionRef:
        obj.x = 20 obj.y = 12
     
    5- Apres FonctionRef
        mavar.x = 20 mavar.y = 12
    te montre ( en 4 et en 5) que mavar est bel et bien modifié quand elle est passée à FonctionRef.

    L'une des solution est, donc, effectivement, de passer un objet qui ne doit pas etre modifié par la fonction par valeur plutot que par référence.

    Cependant, car rien n'est jamais simple en informatique, le passage d'argument par valeur peut avoir, lui aussi, des conséquences dramatiques - ne serait-ce que au niveau des performances sur les objets importants - parce qu'il implique la copie intégrale de l'objet.

    C'est la raison pour laquelle on préférera souvent utiliser le mot cle const et le passage d'argument par référence pour les gros objets.

    Ce mot clé indique simplement au compilateur que
    Citation Envoyé par le programmeur au compilateur
    Attention, je te passe l'objet lui-meme (par référence) mais je m'engage à ne pas le modifier
    Le compilateur étant alors au courent de ton engagement ne se genera pas pour t' "insulter" si tu essaye malgré tout de modifier l'objet dans la fonction.

    C'est ce que l'on appelle, en anglais une construction "const-correct" (correcte du point de vue de la constance)

    Le problème est encore plus subtil pour ce qui concerne les retours de fonctions.

    Quelque chose à laquelle on ne pense pas (forcément), c'est, par exemple, le fait qu'une variable locale est détruite une fois que l'on sort de la portée (pour faire simple le couple d'accolades) dans laquelle elle est déclarée.

    Ainsi, un code du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    typeperso& MaFonction()
    {
        typeperso ret;
        /* toute la gestion du type perso */
        return ret;
        /* Attention!!! ret est detruit lorsque l'accolade fermante est atteinte */
    }
    /* appelée sous la forme de */
    typeperso mavar=MaFonction();
    aurait l'effet de bord (parce qu'il correspond au comportement inhérent à la définition de "portée") que mavar va correspondre à une variable... qui n'existe plus, et dont la mémoire est susceptible d'etre réutilisée pour autre chose
    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 du Club
    Inscrit en
    Septembre 2006
    Messages
    86
    Détails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 86
    Points : 48
    Points
    48
    Par défaut
    Citation Envoyé par koala01
    Salut,

    D'abord, il semble intéressant de s'assurer que tu aies bien compris la différence entre le fait de passer un ojet par valeur et celui de passer un objet par référence.

    Quand tu crées des fonctions dont le prototype est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    void FonctionVal(type obj);
    /* ou */
    void FonctionRef(type& obj);
    /* qui seraient utilisées sous une forme proche de */
     
    type mavar;
    FonctionVal(mavar);
    /*ou */
    FonctionRef(mavar);
    FonctionVal va travailler avec une copie de mavar, alors que FonctionRef va travailler avec mavar lui-meme.

    Du coup, si dans FonctionVal, tu modifie obj, mavar n'est pas modifiée une fois que la fonction a été appelée. Par contre, si tu modifie obj dans FonctionRef, les modification apportées seront répercutées sur mavar.

    Et c'est là que réside le principal effet de bord.

    On parle plus volontiers d' "effet de bord" que d' "effet secondaires" parce qu'un effet secondaire a cette connotation de "effet indésiré", alors qu'un effet de bord indique qu'il s'agit d'un comportement tout à fait cohérent avec la définition que l'on donne d'un terme, mais auquel on ne pensera pas forcément... avant de s'etre fait avoir

    Ceci étant dit, l'implémentation de ce que j'ai expliqué plus haut sous la forme de
    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
    #include <iostream>
     
    using namespace std;
    struct type
    {
        int x;
        int y;
    };
    void FonctionVal(type obj)
    {
        obj.x+=2;
        obj.y*=2;
        cout<<"2- Dans FonctionVal:"<<endl
            <<"    obj.x = "<<obj.x<<" obj.y = "<<obj.y<<endl<<endl;
    }
    void FonctionRef(type& obj)
    {
        obj.x*=2;
        obj.y+=2;
        cout<<"4- Dans FonctionRef:"<<endl
            <<"    obj.x = "<<obj.x<<" obj.y = "<<obj.y<<endl<<endl;
    }
    int main()
    {
        type mavar={10,10};
        cout<<"1- A la creation :"<<endl
            <<"    mavar.x = "<<mavar.x<<" mavar.y = "<<mavar.y<<endl<<endl;
        FonctionVal(mavar);
        cout<<"3- Apres FonctionVal"<<endl
        <<"    mavar.x = "<<mavar.x<<" mavar.y = "<<mavar.y<<endl<<endl;
        FonctionRef(mavar);
        cout<<"5- Apres FonctionRef:"<<endl
        <<"    mavar.x = "<<mavar.x<<" mavar.y = "<<mavar.y<<endl<<endl;
        return 0;
    }
    dont le code compile et fournit la sortie
    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
     
    1- A la creation:
        mavar.x = 10 mavar.y = 10
     
    2- Dans FonctionVal:
        obj.x = 12 obj.y = 20
     
    3- Apres FonctionVal:
        mavar.x = 10 mavar.y = 10
     
    4- Dans FonctionRef:
        obj.x = 20 obj.y = 12
     
    5- Apres FonctionRef
        mavar.x = 20 mavar.y = 12
    te montre ( en 4 et en 5) que mavar est bel et bien modifié quand elle est passée à FonctionRef.

    L'une des solution est, donc, effectivement, de passer un objet qui ne doit pas etre modifié par la fonction par valeur plutot que par référence.

    Cependant, car rien n'est jamais simple en informatique, le passage d'argument par valeur peut avoir, lui aussi, des conséquences dramatiques - ne serait-ce que au niveau des performances sur les objets importants - parce qu'il implique la copie intégrale de l'objet.

    C'est la raison pour laquelle on préférera souvent utiliser le mot cle const et le passage d'argument par référence pour les gros objets.

    Ce mot clé indique simplement au compilateur que


    Le compilateur étant alors au courent de ton engagement ne se genera pas pour t' "insulter" si tu essaye malgré tout de modifier l'objet dans la fonction.

    C'est ce que l'on appelle, en anglais une construction "const-correct" (correcte du point de vue de la constance)

    Le problème est encore plus subtil pour ce qui concerne les retours de fonctions.

    Quelque chose à laquelle on ne pense pas (forcément), c'est, par exemple, le fait qu'une variable locale est détruite une fois que l'on sort de la portée (pour faire simple le couple d'accolades) dans laquelle elle est déclarée.

    Ainsi, un code du genre
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    typeperso& MaFonction()
    {
        typeperso ret;
        /* toute la gestion du type perso */
        return ret;
        /* Attention!!! ret est detruit lorsque l'accolade fermante est atteinte */
    }
    /* appelée sous la forme de */
    typeperso mavar=MaFonction();
    aurait l'effet de bord (parce qu'il correspond au comportement inhérent à la définition de "portée") que mavar va correspondre à une variable... qui n'existe plus, et dont la mémoire est susceptible d'etre réutilisée pour autre chose
    Merci beaucoup koala01.... C'etais tres clair et ca repond a ma question.. je te remerci.

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

Discussions similaires

  1. Pointeur de pointeur en passage par reference.Debutant.
    Par Freedom57 dans le forum Débuter
    Réponses: 6
    Dernier message: 06/02/2011, 12h00
  2. Passage par reference
    Par Seth77 dans le forum Langage
    Réponses: 38
    Dernier message: 03/09/2008, 17h38
  3. Probleme sur le passage par reference
    Par schnito dans le forum Langage
    Réponses: 10
    Dernier message: 02/02/2006, 16h50
  4. [Debutant(e)]passage par adresse?
    Par cap2fosse dans le forum Langage
    Réponses: 4
    Dernier message: 24/09/2004, 10h05
  5. [VB6]Passage par référence d'une prop. d'objet à une fct
    Par -gYs- dans le forum VB 6 et antérieur
    Réponses: 15
    Dernier message: 02/09/2002, 08h55

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