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 :

fonction:passage par valeur ou référence


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2006
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Septembre 2006
    Messages : 286
    Par défaut fonction:passage par valeur ou référence
    bonjour à tous,
    La fonction FcIntStr,dont code ci-dessous, ne répond pas à mon attente.
    Je voudrais une sortie sous les lignes Ch ou CA de préférence à celle de St.
    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
     
     
    //essai 
    //#include <string>
    #include <iostream>
    #include <sstream>  
    //#include <fstream>
     
    using namespace std;
     
    string FcIntStr(int NbA,string ChA,int fcvue)
    {//29/12/11/22h
    //IntVerStr=FcIntStr(nb,ch,fcvue); 
         ostringstream ossNbA;
         ossNbA<<NbA;
         ChA=ossNbA.str();
    return ChA;      
    }//29/12/11/22h
     
    int main()
    {   
        int fcvue=0;
        cout<<"essai int vers string"<<endl; 
        int nb=15;
        string Ch;
        string ChA;
        string IntVerStr;
     
        IntVerStr=FcIntStr(nb,Ch,fcvue);
     
        cout<<"St "<<IntVerStr<<endl;
        cout<<"It "<<nb <<endl;
        cout<<"CA "<<ChA<<"*"<<endl;//pourquoi vide?  
        cout<<"Ch "<<Ch <<"*"<<endl;//pourquoi vide?
     
        cout<<"<E>";cin.get();
    }
    La fonction doit être mal écrite()?
    Merci pour cette étude.

  2. #2
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    ChA est vide car elle n'est pas initialisé autrement qu'à la construction. Ne pas confondre ChA dans la fonction main et ChA dans la fonction FcIntStr. Bien qu'elles aient le même nom, ce sont bien deux variables différentes car sises dans des 'portées' (~blocs) différents.

    Ch est vide car la fonction FcIntStr prend son argument par valeur. Cela signifie qu'il fait une copie de l'argument avant d'entrer dans la fonction. Toute modification dans la fonction se faisant sur la copie, cela n'aura pas d'impact sur l'argument passé en paramètre. Il faudrait utiliser un passage par référence si tu voulais modifier l'argument :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    string FcIntStr(int NbA,string &ChA,int fcvue)
    {//29/12/11/22h
    //IntVerStr=FcIntStr(nb,ch,fcvue);
         ostringstream ossNbA;
         ossNbA<<NbA;
         ChA=ossNbA.str();
    return ChA;
    }//29/12/11/22h

  3. #3
    Membre très actif
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2006
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Septembre 2006
    Messages : 286
    Par défaut
    Bonjour et merci pour ce petit cours de C++/dev-cpp.
    J'ai d'autres fonctions du même tonneauJe vais les transformer avec le
    dopant "&".
    Merci beaucoup(..et rapide!)

  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,

    En fait, ta fonction renvoie une chaine de caractères et je ne vois donc pas pourquoi tu voudrais que la chaine de caractères passée en argument soit modifiée

    Je ne dis pas que ce n'est pas juste que de faire en sorte que la chaine de caractères passée en argument soit modifiée, car cela peut avoir un sens, mais, ce que je dis, c'est que le nom de ta fonction et celui des paramètres n'est pas suffisamment bien choisi pour nous permettre de nous faire une idée de l'opportunité qu'il peut y avoir à ce que ce soit le cas

    Je m'explique:

    La logique que tu places dans ta fonction est sensée modifier ChA et renvoyer ChA sous la forme de valeur, mais, est-ce vraiment utile

    En effet, si tu récupères la chaine renvoyée par ta fonction dans une autre variable que celle qui est passée comme étant ChA, tu auras deux variables qui auront exactement la même valeur : la variable passée en tant que paramètre et celle qui aura récupéré le retour de la fonction...

    Qu'est ce qui pourrait justifier ce fait

    Tu as, en effet, deux solutions:

    Soit, tu te dis que tu veux modifier une variable qui existe dans la fonction appelante (cela peut avoir un sens, s'il est question de concaténer des données ) et, à ce moment là, tu n'as pas besoin de la valeur de retour, avec un code proche 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
     
    void foo(int NbA,string &ChA)
    {
        std:::stringstream ss;
        ss<<NbA<<ChA;
        ChA == ss.str();
    }
    int main()
    {
        std::string truc="machin";
        int basard = 10;
        foo(basard, truc);
        /* truc="10machin" ;) */
    }
    Soit tu te dis que, ce qui t'intéresse, c'est le retour de ta fonction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    std::string bar(int NbA,std::string const &ChA) // le fait de passer la chaine
                                         // sous la forme d'une référence constante évite
                                         // la copie de la chaine, mais empêche qu'elle soit
                                         // modifiée
    {
        std:::stringstream ss;
        ss<<NbA<<ChA;
        return ss.str();
    }
    et tu peux alors décider soit de récupérer le résultat dans une autre variable, soit de le récupérer dans une variable existante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    int main()
    {
        std::string truc="truc";
        int basard = 10;
        truc=bar(10,truc); // oui oui, ca marche :D : truc = "10truc"
        /* OU OU OU OU */
        std::string brol="brol";
        int bidule = 20;
        std::string recup=bar(bidule, brol);
        /* brol = "brol", recup = "20brol" */
        /*...*/ 
        return 0;
    }
    Par contre, le fait de mélanger les deux est, très certainement, le meilleur moyen d'avoir un "effet de bord" aux effets des plus désagréables et difficiles à retrouver...

    Imagine un peu les fonctions
    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
    std::string bar(int i, std::string & str)
    {
        std:::stringstream ss;
        ss<<NbA<<str;
        str== ss.str();
        return str;
    }
    void foo(std::string & str)
    {
        int i = 10;
        /*... */
        std::string temp = bar(i, str);
        /* ici, on travaille avec temp  ;) */
    }
    int main()
    {
        std::string truc="truc";
        /* 15 instructions */
        foo(truc);
        /* 15 instructions */
       /* je voudrais que truc vaille "10truc" :D */
       bar(10,truc);
       std::cout<<truc<<std::endl; //Mais pourquoi truc, qui est sensée valoir
                                   // "10truc" vaut elle "1010truc" ????
       return 0;
    }
    Ici, le cas est relativement simple, et il apparaitra (relativement) vite que truc vaut déjà "10truc" bien avant que tu n'appelles bar() dans main() (à cause de l'appel à foo() ), mais c'est typiquement le genre de choses, lorsque tu as des fonctions qui appellent des fonctions qui appellent des fonctions qu'il te sera très difficile de repérer, surtout si tes fonctions sont un tant soit peu complexes

    Moralité : évites toi bien des soucis et évite qu'une valeur de retour soit identique à la nouvelle valeur d'un argument passé en entrée / sortie
    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 très actif
    Homme Profil pro
    retraité
    Inscrit en
    Septembre 2006
    Messages
    286
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Indre et Loire (Centre)

    Informations professionnelles :
    Activité : retraité

    Informations forums :
    Inscription : Septembre 2006
    Messages : 286
    Par défaut
    Merci pour ces hautes et logiques considérations qui ont une grande valeur.
    Le & ajouté à la "variable" sort me suffit.Je vais veiller à la construction des noms des variables.
    Bien noter que j'ai modifié sort en sortie car sort est un mot réservé....tri en français.
    Merci à tous.

  6. #6
    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
    As-tu seulement compris tout ce que ce petit "&" implique et le sens de mon intervention

    Mon intervention avait pour but de te faire prendre conscience que tu est de toute évidence face à un problème de conception dés le moment où tu envisage de faire en sorte qu'une variable passée en argument soit modifiée d'un coté tout en récupérant le résultat de cette modification par la valeur de retour de la fonction!!!

    Comme l'indiquaient les portions de code que j'ai fournies (et surtout les commentaires que j'ai pris la peine de rajouter ), tu risques vraiment de te retrouver avec des valeurs qui peuvent te sembler incohérentes, simplement parce que l'appel d'une fonction aura eu pour résultat d'appeler une fonction qui apportera des modifications auxquelles tu ne penses peut etre pas

    Le fait qu'une fonction modifie une variable qui lui est passée en argument est ce que l'on appelle couramment un "effet de bord" et il s'agit de se méfier comme de la peste de ces derniers, parce qu'il est particulièrement difficile d'avoir un aperçu clair et précis de la manière dont il va se répercuter dans le code

    De plus, le caractère "&" n'est pas un caractère magique intervenant dans une quelconque pratique vaudou!!

    C'est le symbole qui, utilisé sous la forme présentée ici, indique que l'on travaille avec une référence sur un objet.

    Le fait de travailler avec des références présente énormément d'avantages, mais nécessite aussi d'aborder les choses avec la plus grande discipline possible:

    Du fait que l'on travaille en réalité avec un alias de l'objet référencé, il faut être conscient que tout ce qui arrive à la référence arrivera en réalité à l'objet référencé et que l'idéal reste donc de toujours éviter les effets de bord en déclarant constant tout ce qui peut l'être, justement pour éviter qu'une modification n'aille prendre effet sur quelque chose que l'on n'imagine peut etre pas

    Je ne peux donc que t'inciter à méditer sur ce que je viens d'écrire et à prendre en compte ces remarques, meme si c'est sur un "petit projet", ne serait ce que pour t'habituer directement à faire du travail correct
    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

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

Discussions similaires

  1. Passage par valeur & passage par référence
    Par maiza_med dans le forum C++
    Réponses: 13
    Dernier message: 28/02/2015, 02h02
  2. fonction passage par valeur ,par adresse
    Par hybride11 dans le forum C
    Réponses: 2
    Dernier message: 21/08/2010, 18h25
  3. passage paramètre par valeur et référence
    Par new_wave dans le forum Débuter avec Java
    Réponses: 2
    Dernier message: 09/03/2008, 18h53
  4. Passage par Valeur
    Par xc78370 dans le forum Langage
    Réponses: 8
    Dernier message: 20/03/2006, 23h21
  5. Passage par valeur / passage par adresse
    Par jeje99 dans le forum C++
    Réponses: 13
    Dernier message: 16/02/2006, 10h29

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