Partage
  • Partager sur Facebook
  • Partager sur Twitter

Portée des variables

Pour quelle rasion tangible et vérfiable ce code fonctionne bien?

    4 août 2023 à 21:43:54

    Le code en question

    Merci pour votre patience

    #include <iostream>
    using namespace std;


    void incrementer(int &a)
        {
            a++;
        }


    int main()
    {
        int a = 15;
        incrementer (a);
        cout<<"a =  "<<a<<endl;
        return 0;
    }

    • Partager sur Facebook
    • Partager sur Twitter
      4 août 2023 à 21:48:48

      Parce qu'il respecte les spécifications définies dans la norme C++ et implémentés dans les compilateurs
      • Partager sur Facebook
      • Partager sur Twitter
        5 août 2023 à 0:46:21

        Il y a dans main() une variable a. Il y a dans incrementer() une variable qui référence la variable a reçue.

        Curieusement la variable a de main() et la variable a de incrementer() portent le même nom. Utiliser des noms de variables explicites améliorerait la lisibilité et la compréhension.

        • Partager sur Facebook
        • Partager sur Twitter

        En recherche d'emploi.

          5 août 2023 à 1:32:40

          Ceci fonctionne également:
           
          #include <iostream>
          void incrementer(int &formel) {
                  formel++;
              }
          int main(void) {
              int actuel = 15;
              incrementer (actuel);
              std::cout << "a =  " << actuel << std::endl;
              return 0;
          }
           
          Puisque tu parles de portée des variables, les paramètres d'une fonction font partie de la portée de cette fonction.
          • Partager sur Facebook
          • Partager sur Twitter

          Le Tout est souvent plus grand que la somme de ses parties.

            5 août 2023 à 1:49:16

            Salut,

            Pour ce qui concerne la portée des variables, on va faire simple : elle s'étend de la ligne de code où les variables sont déclarées jusqu'à l'accolade fermante correspondant au bloc d'instructions dans lequel elles sont déclarées, c'est à dire que nous pourrions avoir les situations suivantes:

            int main(){
                int a;  
                /* a est disponnible ici, mais ni b, ni c, ni d ne le sont */
                if( condition){
                    int b;
                    /* a et b sont disponnibles ici, mais ni c ni d ne le sont */
                } // b est détruit ici
                else{
                    int c;
                    /* a et c sont disponnibles ici, mais ni b ni d ne le sont */
                }   c est détruit ici
                int d;
                /* a et d sont disponnibles ici, mais ni b ni c ne le sont */
             } // d est détruit en premier ici
               // ensuite, c'est le tour de a
            

            Vient ensuite le "problème de la transmisson d'informations à aux fonctions (sous la forme de paramètres):

            Par défaut (lorsque l'on déclare un argument sans ajouter aucune information autre que son type et son nom), la transmission se fait par copie.

            C'est à dire que la variable qui est utilisée dans la fonction appelée est une variable différente de celle qui a été transmise au niveau de la fonction appelante.

            Le code qui suit montre bien la situation:

            void argumentParValeur(int i){
                std::cout<<"la fonction a recu l'argument i dont\n 
                           "la valeur d'origine est "<<i<<"\n";
                i*=2;
                std::cout<<"après avoir multiplié i par deux, sa valeur\n"
                         <<"dans la fonction argumentParValeur est "
                         <<i<<"\n";
            }
            int main(){
                int valeurATransmettre = 3;
                std::cout<<"dans la fonction main, la valeur de la variable \n"
                         <<"'valeurATransmettre' est "
                         <<valeurATransmettre<<"\n";
                 argumentParValeur(valeurATransmettre);
                 std::cout<<"apres l'appel à la foncion argumentParValeur,\n";
                          <<"la valeur de valeurATransmettre est "
                          <<valeurATransmettre<<"\n";
            }

            Cependant, il existe le concepte de référence (int & ref), qui n'est, pour faire simple, que l'allias d'une donnée existante ailleurs.  Si c'était une personne, nous pourrions parler de pseudonyme, un peu comme  "Jean-Michel Smets" était plus connu sous le pseudo "Jhonny Halliday" ou comme je suis moi-même plus connu sur les formums sous le pseudo dekoala01 est le pseudo de ... koala01:

            Tout ce que Jhonny a pu chanter, c'est en réalité Jean Michel Smets qui l'a chanté.   Tout ce qui a pu arriver à Jhonny, c'est en réalité arrivé à ... Jean Michel Smets.

            Et tout ce que koala01 peut écrire sur les forum, c'est en réalité ... moi qui l'écrit.

            Cela implique que tout ce qui pourra arriver à un argument passé sous forme de référence à une fonction arrivera en réalité à la variable qui a été transmise au niveau de la fonction appelante.

            Voici, encore une fois, un petit code qui montre la situation:

            void argumentParReference(int & ref){
                std::cout<<"la fonction a recu l'argument ref dont\n 
                           "la valeur d'origine est "<<ref<<"\n";
                ref*=2;
                std::cout<<"après avoir multiplié ref par deux, sa valeur\n"
                         <<"dans la fonction argumentParReference est "
                         <<ref<<"\n";
            }
            int main(){
                int valeurATransmettre = 3;
                std::cout<<"dans la fonction main, la valeur de la variable \n"
                         <<"'valeurATransmettre' est "
                         <<valeurATransmettre<<"\n";
                 argumentParReference(valeurATransmettre);
                 std::cout<<"apres l'appel à la foncion argumentParReference,\n";
                          <<"la valeur de valeurATransmettre est "
                          <<valeurATransmettre<<"\n";
            }

            Ce qu'il faut savoir, c'est que ces deux comportements sont précisément décrits "tels quels" dans la spécification (dans la norme) du langage: "on" a décidé une bonne fois pour toute qu'il y aura copie lorsque le paramètre est transmis par valeur, et qu'il y aura création d'un alias sur la variable référencée lorsque le paramètre est transmis par référence.

            Bien sur, on pourrait jouer de la même manière avec les copies et les références sans passer par des fonctions intermédiaires, en déclarant les copies et les références dans la même fonction que celle dans laquelle la variable d'origine est déclarée.

            Mais, dans l'absolu, les cas dans lesquels il serait effectivement opportun de le faire sont tellement rares (hormis l'apprentissage, peut-être) qu'il me semble plus cohérent de passer directement à l'étape qui consiste à l'utilisation d'informations transmises à une fonction séparée, car ce cas de figure correspondra à la très grosses majorité des cas dans lesquels tu devras choisir entre l'utilisation d'une copie ou d'une référence ;)

            • Partager sur Facebook
            • Partager sur Twitter
            Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait

            Portée des variables

            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
            • Editeur
            • Markdown