Partage
  • Partager sur Facebook
  • Partager sur Twitter

Conteneurs et Pointeurs

Clarification du Cours

Sujet résolu
    20 janvier 2020 à 14:47:35

    Je suis débutant en C++ et je commence à avoir des difficultés en ce qui concerne les conteneurs et les pointeurs.

    Déjà, si j’ai bien compris le cours, il faut déclarer l’argument de type conteneur (vector ou autre) en tant que référence dans le prototype d’une fonction pour ne pas qu’il soit copié intégralement lors de l’utilisation de celle-ci.

    Ma question est donc la suivante : si ce conteneur contient des objets, et que je veux modifier ces objets et non pas une copie de ces objets, dois-je également passer en argument une référence vers un conteneur de référence vers ces objets.

    En gros est-ce que je dois faire cela :
    1)maFonction(vector<Objet> &tab)

    OU

    2)maFonction(vector<&Objet> &tab)

    Par ailleurs, si c’est l’alternative 2 qu’il faut choisir alors que faut-il passer en paramètre dans la fonction appelante :

    1)
    vector<Objects> objets;
    maFonction(objets);

    OU ALORS

    2)
    vector<Object> objets;
    //…Ajouts d’Object dans objets
    vector<&Objects> objets_ref;
    //PARCOURIR TOUS LES OBJETS
     for (Vertice v : objets) //
     {
        //On met à chaque fois l’adresse de v dans le conteneur objets_ref
            objets_ref.push_back(&v)
     }
    maFonction(objets_ref)

    Enfin, pourriez m’expliciter un peu la différence entre les références &ref qu’on déclare dans les arguments d’une fonction et celles que l’on déclare telle quelles dans le code (&ref = i) car je m’embrouille souvent entre les deux.

    Voilà,

    Axel.
    • Partager sur Facebook
    • Partager sur Twitter
      20 janvier 2020 à 15:07:59

      >dois-je également passer en argument une référence vers un conteneur de référence vers ces objets.

      Non, juste une référence "non-const" sur le conteneur 'initial' fera l'affaire.

      donc 1) et 1)

      Attention, il ne faut confondre référence et adresse d'une variable.

      Références :

      int& FonctionRetournantUneReferance();
      void FonctionPrenantUneReferenceEnParametre(Object& obj);
      
      int& ref = FonctionRetournantUneReferance();
      ...
      
      Object object;
      FonctionPrenantUneReferenceEnParametre(object);



      Adresse de variable :

      int* ptr = &var;



      -
      Edité par bacelar 20 janvier 2020 à 15:08:46

      • Partager sur Facebook
      • Partager sur Twitter
      Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
        20 janvier 2020 à 16:37:52

        Merci beaucoup pour ces réponses.
        • Partager sur Facebook
        • Partager sur Twitter
          24 janvier 2020 à 13:16:55

          Re Bonjour,

          J'ai mis ce sujet résolu mais je voudrais revenir sur ta dernière réponse concernant la différence entre référence et adresse.

          -->"Attention, il ne faut confondre référence et adresse d'une variable."

          Je pense en effet avoir légèrement confondu les deux pendant un certain temps... Cependant ces deux notions m'ont l'air très proche et j'aimerais avoir quelques explicitations :

          1) Dans ton exemple, tu as mis le prototype d'une fonction retournant une référence, ce qui indique (si je ne me trompe pas) que tu retourne l'adresse du int et non pas une copie ?

          2) Si je prends l'exemple des références en paramètre d'une fonction, on a besoin de mettre un & avant le paramètre pour dire qu'il s'agit d'une variable et non pas d'une valeur copié... Mais on utilise pas le & lors de l'appel de la fonction comme tu l'as fait à la fin pour l'objet :

          "FonctionPrenantUneReferenceEnParametre(object);" et non pas "FonctionPrenantUneReferenceEnParametre(&object);"

          On passe l'objet telle quelle lors de l'appel et si c'est une référence qui est marquée dans le prototype alors on modifiera la variable et non pas une copie (jusque là je pense avoir bon ?).

          Pourtant, j'ai l'impression que ce principe n'est pas respecté en ce qui concerne le type de retour d'une fonction.

          En effet, tu donnes l'exemple d'une fonction retournant une référence : "int& FonctionRetournantUneReferance();"

          Mais le type de retour est un int& et non pas un int... Je ne sais pas si tu vois ce que je veux dire mais j'ai l'impression que la "symétrie" entre l'appel et le retour par référence n'est pas respectée.

          3) Enfin, pour retourner une référence telle que dans l'exemple que tu as donnée "int& ref = FonctionRetournantUneReferance()",comment faut-il faire dans la définition de la fonction au moment du retour ?

          int& FonctionRetournantUneReferance()

          {

          int nombre

          return &nombre ou return nombre ??

          }

          Merci,

          Axel.

          -
          Edité par kenroll 24 janvier 2020 à 13:21:19

          • Partager sur Facebook
          • Partager sur Twitter
            24 janvier 2020 à 14:38:48

            >que tu retourne l'adresse du int et non pas une copie ?

            Non, pas une adresse, une référence, c'est pas tout à fait la même chose.

            Par exemple, une référence ne peut pas être null (nullptr), c'est forcement une référence vers un truc qui existe.

            Mais, oui, il n'y a pas "copie".

            >on a besoin de mettre un & avant le paramètre pour dire qu'il s'agit d'une variable

            Attention au terme "variable" qui est poli-sémique donc très très ambiguë.

            Comme c'est montré dans l'extrait de code (dans la déclaration de fonction "FonctionPrenantUneReferenceEnParametre") que j'ai fourni ("...Object& parametre1..." et pas "...Object &parametre1...), c'est plus ajouter "&" à la fin du type du paramètre pour indiquer que c'est une référence qu'on passe en argument.

            >On passe l'objet telle quelle lors de l'appel

            On passe une référence sur l'objet, pas l'objet lui-même, mais ça n'invalide pas votre raisonnement.

            On utilise une référence sur une variable comme si c'était une variable "pleine", contrairement aux pointeurs.

            Mais en sous-marin, la référence planque un pointeur pour faire son taf.

            >en ce qui concerne le type de retour d'une fonction.

            Bin si, c'est une référence qu'on retourne, pas un objet "plein".

            >comment faut-il faire dans la définition de la fonction au moment du retour ?

            Attention à na pas utiliser de référence sur des variables locales hors de la fonction qui l'a déclaré.

            class toto{
                int m_nombre;
            ...
            public :
            ...
                int& FonctionRetournantUneReferance();
            ...
            }
            
            int& toto::FonctionRetournantUneReferance()
            {
                return m_nombre;
            }



            • Partager sur Facebook
            • Partager sur Twitter
            Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
              24 janvier 2020 à 15:08:56

              Je te remercie de tes réponses qui ciblent exactement ce que je voulais savoir.

              Si j’ai bien compris, le terme référence concerne surtout les fonctions et leurs paramètres ainsi que leur type de retour pour dire si on effectue des traitements sur l’élément lui-même ou alors sur une copie et si on retourne l’element lui même ou alors une copie.

              Au passage, peux-tu expliciter ton dernier point concernant les références et les variables locales aux fonctions ?

              Une référence déclaré hors d’une fonction, c’est un peu comme un pointeur constant ? 

              Enfin, pour revenir au sujet initial qui était les conteneurs : est-ce que cela a du sens de faire cela : vector<Objet&> ? Si oui lequel ?

              Si non, comment dois-je faire pour faire une collection d’Objet sans les recopier ? Désolé d’insister là dessus mais c’est vraiment important pour moi...

              • Partager sur Facebook
              • Partager sur Twitter
                27 janvier 2020 à 10:35:09

                >le terme référence concerne surtout les fonctions et leurs paramètres

                Non, cela concerne aussi les variables locales à une fonction ou les champs d'une classe.

                >ainsi que leur type de retour

                Avec les nouvelles normes du C++ (avec les copies élisions), il est maintenant assez rarement judicieux de retourner des références.

                >si on effectue des traitements sur l’élément lui-même ou alors sur une copie

                Oui

                >et si on retourne l’element lui même ou alors une copie.

                Non, pas trop sur les valeurs de retour, c'est très spécial de retourner une référence. c'est plus un choix sémantique que technique/d'optimisation.

                >dernier point concernant les références et les variables locales aux fonctions ?

                La variable locale est "détruite" avant de sortir de la fonction, alors avoir une référence (ou un pointeur) dessus, c'est le meilleur moyen d'avoir un segmentation fault (voire pire, pas d'erreur et défoncer des valeurs de variables qui n'ont rien à voir avec la choucroute).

                > c’est un peu comme un pointeur constant ?

                Absolument pas constant, c'est plus un pointeur qui ne peut pas être "nullptr" et qui utilise une syntaxe comme un objet et pas celles de pointeurs ("." vs "->").

                >est-ce que cela a du sens de faire cela : vector<Objet&>

                Vous ne vous posez pas les bonnes questions pour choisir vos structures de données.

                Une chose qui arrive bien avant de savoir comment éviter les recopies, c'est de savoir qui est "responsable" (ownership) des objets dans les conteneurs.

                Sinon, il y a aussi des fonctions/classe pour se libérer de quelques menu restrictions.

                https://en.cppreference.com/w/cpp/utility/functional/reference_wrapper

                • Partager sur Facebook
                • Partager sur Twitter
                Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.

                Conteneurs et Pointeurs

                × 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