Partage
  • Partager sur Facebook
  • Partager sur Twitter

move: on m aurait menti?

Sujet résolu
    18 août 2018 à 13:18:28

    #include <iostream>
    
    using namespace std;
    int g(int j) {
    return j+1;
    }
    int main()
    {
        int albert=2;
      int bebert=0;
    bebert=g(move(albert));
    cout<<bebert<<endl;
    albert+=5;
    cout<<albert<<endl;
    }
    resultat console:
    3
    7

    Process returned 0 (0x0)   execution time : 0.029 s
    Press any key to continue.
    je m attendais a une erreur de compile ou un resultat a faire exploser mon ordinateur...
    :
    déplacement = changement de l'adresse d'un objet, l'objet est conservé à l'identique. L'objet initial n'est plus valide.

    -
    Edité par GouyFred 18 août 2018 à 13:28:03

    • Partager sur Facebook
    • Partager sur Twitter
      18 août 2018 à 14:33:33

      > déplacement = changement de l'adresse d'un objet, l'objet est conservé à l'identique. L'objet initial n'est plus valide.

      Non, un objet (comprendre une variable) ne change pas d'adresse. Du début à la fin de sa vie qui se situe à la fermeture d'un bloc (}), l'adresse reste la même, quelles que soient les opérations effectuées dessus.

      Ce que fait std::move est de transformer une référence (lvalue) en une rvalue, rien de plus. Ce sont les constructeurs et operator d'affectation de déplacement (ceux qui prennent une rvalue) qui vont modifier l'objet. Le comportement est entièrement décidé par le développeur de la classe.

      Les types scalaires n'ont pas de comportement spécifique avec les rvalues et font des copies. Mettre un comportement spécifique n'est utile que sur des objets manipulation une ressource, car la copie est coûteuse ou parce que les copies sont interdites et que pour qu'une ressource ne se retrouve pas dans 2 instances différente il faut invalider l'instance déplacée.

      Par exemple, une copie de std::vector va copier tous ces éléments, alors qu'un déplacement va copier uniquement les 3 pointeurs internes et mettre à nul ceux d'origine: les éléments du vecteur ne sont pas copiés, ni déplacés puisqu'on n'y touche pas.

      • Partager sur Facebook
      • Partager sur Twitter
        18 août 2018 à 15:37:31

        "Contrairement a la copie qui permet d'obtenir deux objets au final, le deplacement ne modifie pas le nombre d'objets, il y a toujours un seul objet valide apres l'operation. La variable qui contenait l'objet initialement contient ensuite un objet invalide qui ne doit jamais etre utilise (cela produirait un comportement indefini). La variable ne peut etre utilisee que pour lui affecter un nouvel objet."

        http://guillaume.belz.free.fr/doku.php?id=references

        les 2phrases(celle du post d avant et celle du dessus)sont tirées du cour de gbdivers..dans mon exemple ca veut dire quoi que je puisse encore utiliser albert apres le move?

        En gros qu est ce qu on entend par invalide?

        Est ce que ca veut dire que je peux encore l utiliser parceque le  programme n a pas affecté l emplacement mémoire associé a albert a autre chose?

        autrement dit est qu ici albert  affiche la valeur 7(qui celle qu on aurait pu attendre apres une copie) parceque

        1/ le compilateur ne controle pas ce genre de comportement illicite

        2/au moment ou mon programme a été chercher dans cette variable elle n avait pas encore réaffecté

        en tout cas avec les vectors j ai pas d erreur de compile mais le programme plante quand je lui demande la valeur d albert[0]

        hmmmm toujours sur son cours:

        std::move

        Pour être plus précis sur le rôle de la fonction std::move, celle-ci ne “déplace” pas les objets ou n'autorise pas le compilateur a faire un déplacement. Elle convertie simplement une valeur en rvalue-reference. Le compilateur va donc interpréter cette valeur comme si c’était une valeur temporaire et pourra appliquer les optimisations compatibles avec un temporaire (déplacement ou copie le cas échéant).

        donc ca ca rejoint le

        "2/au moment ou mon programme a été chercher dans cette variable elle n avait pas encore réaffecté"?

        ou je suis toujours a coté de la plaque?

        parceque j ai fait plusieurs fois l expérience avec les vectors et plusieurs fois avec les int et je suis a 100% de plantage sur les vectors et 100% de "y a pas de probleme" coté int. j ai pas de bol ou je comprends pas (ce qui est pas de bol aussi)?

        -
        Edité par GouyFred 18 août 2018 à 16:00:18

        • Partager sur Facebook
        • Partager sur Twitter
          18 août 2018 à 17:25:56

          GouyFred a écrit:

          La variable qui contenait l'objet initialement contient ensuite un objet invalide qui ne doit jamais etre utilise

          En fait, la variable initiale est dans un etat indetermine, qui ne permet que de detruire l'objet ou d'affecter un nouvel objet a la variable. J'ai prefere simplifier en "invalide", mais ce n'est pas correct. Mais a mon sens, l'important est de comprendre la difference entre la copie et le mouvement. Je vais voir pour ameliorer ca.

          GouyFred a écrit:

          déplacement = changement de l'adresse d'un objet

          C'est tres maladroit de ma part de presenter comme ca, ce qui fait que c'est faux. Je vais supprimer.

          En fait, la version "incorrecte" (qui ne parle de l'adresse) est l'ancienne version, que j'ai reecrite dans la version "correcte" (celle qui est dans http://guillaume.belz.free.fr/doku.php?id=references ). Quand je reecris, je ne pense pas forcement a relire tout le cours pour supprimer ce qui est trop ancien. (Surtout que je ne travaille plus sur le wiki).

          GouyFred a écrit:

          que je puisse encore utiliser albert apres le move?

          Non. La ligne "albert+=5;" est un comportement indefini.

          GouyFred a écrit:

          En gros qu est ce qu on entend par invalide?

          On devrait dire "dans un etat indetermine, mais valide, qui autorise uniquement l'affectation et la destruction". Pour simplifier, on dit souvent "invalide" pour dire "n'y touchez pas".

          GouyFred a écrit:

          Est ce que ca veut dire que je peux encore l utiliser parceque le  programme n a pas affecté l emplacement mémoire associé a albert a autre chose?

          J'explique cela ensuite : "En pratique, ce qui se passe reelement lors d'un deplacement est un peu complexe. Dans certains cas (par exemple avec les types fondamentaux), une copie sera realisee. Dans d'autres cas (par exemple avec std::string ou std::vector), les donnees ne sont reellement pas copiees et le deplacement est plus performant que la copie. Dans tous les cas, vous pouvez retenir que le deplacement ne sera jamais plus couteux que la copie (au pire, il peut etre equivalent a une copie)."

          Donc en gros, c'est trop complique, il y a differents cas possible.

          GouyFred a écrit:

          parceque

          1/ le compilateur ne controle pas ce genre de comportement illicite

          2/au moment ou mon programme a été chercher dans cette variable elle n avait pas encore réaffecté

          en tout cas avec les vectors j ai pas d erreur de compile mais le programme plante quand je lui demande la valeur d albert[0]

          Ce qui se passe pour un entier sur la pile sera different de ce qui se passe pour un vector par exemple. Il faut juste retenir que ce n'est pas valide de continuer a utiliser une variable apres mouvement.

          GouyFred a écrit:

          "2/au moment ou mon programme a été chercher dans cette variable elle n avait pas encore réaffecté"?

          ou je suis toujours a coté de la plaque?

          parceque j ai fait plusieurs fois l expérience avec les vectors et plusieurs fois avec les int et je suis a 100% de plantage sur les vectors et 100% de "y a pas de probleme" coté int. j ai pas de bol ou je comprends pas (ce qui est pas de bol aussi)?

          Non, c'est pas une probleme de "reaffectation" de la variable (ce qui ne veut pas dire grand chose en fait).

          Il ne se passe pas la meme chose en interne pour int et vector. Peut importe ce qu'il se passe. Il ne faut pas faire.

          Un rappel : un comportement indefini ne veut pas dire forcement plantage ou erreur. Tout peut arriver dans ce cas.

          • Partager sur Facebook
          • Partager sur Twitter
            18 août 2018 à 17:35:49

            Daccord merci pour vos réponses et votre patience.

            Merci pour ton cours aussi

            • Partager sur Facebook
            • Partager sur Twitter

            move: on m aurait menti?

            × 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