Partage
  • Partager sur Facebook
  • Partager sur Twitter

A quoi sert le C++ moderne ?

    26 septembre 2021 à 6:24:42

    JadeSalina a écrit:

    Vous savez qu'un raw pointer est la meilleure manière d'exprimer le fait que "la mémoire n'est pas gérée par moi, je ne fais qu'utiliser la ressource merci" ? Et que ça ne veut pas dire qu'il y aura la moindre fuite mémoire ? Comme par exemple

    struct GameState {
      Renderer *renderer;
      // ...
    };
    
    int main() {
      Renderer renderer{};
    
      runGame(&renderer);
    
      return 0;
    }

    Cela dit, c'est un probleme pédagogique classique. Quand on présente ce genre de code a des débutants ou des new/delete, ils se disent : "cool, c'est safe. Il suffit de ne pas oublier le delete".

    Mais ils ne peuvent pas avoir du recul par eux même sur ce genre de code. Si personne ne leur dit, ils ne peuvent pas savoir que les "il suffit" ne suffisent pas dans un code de plusieurs centaines de millier de ligne de code. Ils ne peuvent pas savoir que "il suffit" n'a pas été suffisant pour que des experts en C/C++ ne fasse pas des bugs critiques et sont a l'origine de beaucoup de failles de sécurité pendant des dizaines d’années.

    Et les débutants n'ont pas d'autre choix que de faire confiance a des personnes qui vont leur dire "voila la bonne façon de faire". Parfois, ces personnes connaissent les pratiques, le pourquoi de ces pratiques, ont appris a se remettre en question et a faire évoluer leur pratique au cours du temps. D'autre fois, comme c'est le cas ici avec JadeSalina et les Casey, des personnes n'ont pas appris des erreurs du passé.

    ------------------------------------------------------------------------------------------

    Pour les débutants qui liraient cette discussion et ne sauraient pas quoi faire : vous nous connaissez pas et c'est normal de ne pas nous croire. Quand vous auraient un peu d'ancienneté sur ce forum, vous verrez rapidement les noms qui reviennent souvent pour aider et expliquer en détail.

    En attendant, un conseil : s'il y a une chaîne YouTube a suivre, c'est celle de la CppCon https://www.youtube.com/user/CppCon. C'est LA conférence C++, qui réunit les plus grands experts en C++. Tout y est abordé, aussi bien le bas niveau, que les bonnes pratiques, les futures évolutions (et pourquoi ces évolutions sont intéressantes), l'utilisation du C++ dans pleins de domaine (dont les jeux vidéos). Il y a même des vidéos pour les débutants (la série "Back to basic").

    Si vous êtes très très débutants, vous ne pourrez pas tout suivre. Mais il vaut mieux regarder cette chaîne que du n’importe quoi.

    Et quand vous voulez discuter sur le forum, ne soyez pas comme JadeSalina.

    -
    Edité par gbdivers 26 septembre 2021 à 6:27:12

    • Partager sur Facebook
    • Partager sur Twitter
      26 septembre 2021 à 7:31:12

      Alors, pourquoi ne pas coder en assembleur. On n'a que 3 petites zones par ligne ...
      Pour avoir fait de l'assembleur sur une machine où la zone des instructions n'était pas séparée des données, on peut avoir de mauvaises surprises.
      Par exemple, à cause d'un bug, on allume des bits au hasard et on se demande pourquoi on a codé la modification du registre 2 et c'est le registre 3 qui est utilisé ...
      Le C, c'est de l'assembleur de haut niveau. C'est facile de se retrouver dans le "décor".
      • Partager sur Facebook
      • Partager sur Twitter

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

        26 septembre 2021 à 8:21:14

        PierrotLeFou a écrit:

        Pour avoir fait de l'assembleur sur une machine où la zone des instructions n'était pas séparée des données, on peut avoir de mauvaises surprises.
        Par exemple, à cause d'un bug, on allume des bits au hasard et on se demande pourquoi on a codé la modification du registre 2 et c'est le registre 3 qui est utilisé ...
        Le C, c'est de l'assembleur de haut niveau. C'est facile de se retrouver dans le "décor".


        Je ne suis pas du tout d'accord avec ça :
        1) Que les instructions ne sont pas séparé des données n'a rien n'a voir avec l'asm , tu peux avoir la même problématique en C.
        2) Le C n'est pas de l'assembleur haut niveau , c'est une idée assez répandu qui est assez fausse.

        -
        Edité par HelbaSama 26 septembre 2021 à 8:21:46

        • Partager sur Facebook
        • Partager sur Twitter
          26 septembre 2021 à 8:26:49

          Les problèmes du type "a qui appartient cette donnée allouée dynamiquement  et qui est chargé de la libérer ?" sont beaucoup mieux pris en compte (rust) par le compilateur plutot que par la vigilance supposée du programmeur.

          C++ a en son temps apporté (par rapport à C) la libération automatique des ressources dans les destructeurs, mais c'est notoirement  insuffisant. Borrowing et lifetime vérifiés par le compilateur, c'est l'étape suivante.

          Probleme, c'est délicat d'apprendre à s'en servir quand on a passé des années à programmer n'importe comment :-)

          Mais on a toujours ce problème quand on change les paradigmes de programmation. Knuth a eu du mal à se mettre à la programmation structurée.

          -
          Edité par michelbillaud 26 septembre 2021 à 8:29:55

          • Partager sur Facebook
          • Partager sur Twitter
            26 septembre 2021 à 12:28:57

            > Le simple fait de déclarer un std::vector dans une fonction c'est déjà une grave erreur, et oui je croyais que c'était comme ça qui fallait faire et que le compilateur allait faire "sa magie" bah pas du tout, il se met vraiment à demander de la mémoire à l'OS et appeler des constructeurs de partout même quand c'est pas nécessaire

            Tu m'expliques la différence avec un malloc dans fonction? Et si le buffer tu décide de le sortir pour disposer d'n cache à la main avec des realloc... reste le piège où 80% des newbs èt moins newbs en C vont tomber `ptr = realloc(ptr, ...). La même chose avec un resize sur un vecteur est infiment pus safe. L'étape d'après, utiliser des pools si le bench démontre que les perfs sont insuffisantes.

            Et comme un VDD l'a signalé, les problèmes premiers de temps de boots infernaux sont plus du à l'architecture globale choisie pour tel ou tel autre projet qu'à un malheureux vecteur dans une fonction. Maintenant je suis le premier à faire la chasse aux fonctions appelées des milliards de fois (les images dans le spatial ce n'est pas de la gnognotte) qui retournent des structures dynamiques type vecteurs.

            > [10h ou plutot 640 * 1-2h]
            > Ce que je comprends en lisant ça c'est que vous le prenez de haut en ne considérant même pas la valeur pédagogique démentielle présente dans cette série (sans même parler du côté programmation pure, mais simplement la partie maths/physique et approche de problèmes).

            Du tout. On a juste une vie et nullement le temps de consulter autant de contenus non greppables.

            > Vous savez qu'un raw pointer est la meilleure manière d'exprimer le fait que "la mémoire n'est pas gérée par moi, je ne fais qu'utiliser la ressource merci" ? Et que ça ne veut pas dire qu'il y aura la moindre fuite mémoire ? Comme par exemple

            Ca marche quand il y a une poignée de gens compétants sur un projet et pas plus. Augmente la masse de développeurs, et ça ne suffit plus. Les problèmes d'invariants non maitrisés sont à tous les coins de fonctions. D'où l'intérêt de déléguer la sémantique au typage. C'est Dan Saks dans une de ses dernières confs qui explique très bien les modes de pensée/réflexions différents des populations C qui veulent absolument pouvoir débugger (quitte à virer les optim parce que le as-if ça rend indébuggable), alors que les populations C++ préfèrent exprimer des sémantiques plus fortes et avoir des erreurs de compilations sur des erreurs détectables.

            J'ai déjà parler de Dan Saks dans le liens que j'ai donné plus haut vers un troll sur dvpz qui trouveras à la fin deux vidéo: une de Dan Saks et une de Bartow Stugoz (orthographe totalement incertaine). Je te les recommande vivement.

            > Mais franchement faites comme moi, questionnez-vous, ne restez pas sur une façon de penser, écoutez les autres "sons de cloche"

            C'est exactement ce que j'ai fait quand il y a plus de 20 ans j'ai compris que moderniser nos bases de code C/C++ était salvateur.

            La différence est que l'on a bien plus de d'expérience que toi et que l'on a vu les dégâts des mélanges hasardeux. Et que l'on ne code pas forcément des applis simplistes où tout peux s'allouer au début, que l'on appelle moults fonctions qui peuvent échouer, chose qu'il faut traiter, et donc oui, le RAII est salvateur.

            > heureusement qu’on a if constexpr maintenant

            C'est un total autre débat. Je suis très dubitatif sur le sujet. On abandonne l'OCP avec `if constexpr`. Alors c'est sûr que les spécialisations template c'est relou à écrire (c'est à peine mieux que le xslt AMA), mais du coup ces points de variation ne sont plus extensibles. D'où mon interrogation. C'est comme abandonner les fonctions virtuelles et revenir à 5 ifs en cascade à la place.

            • Partager sur Facebook
            • Partager sur Twitter
            C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
              26 septembre 2021 à 16:51:58

              dragonjoker a écrit:

              > Vous savez qu'un raw pointer est la meilleure manière d'exprimer le fait que "la mémoire n'est pas gérée par moi, je ne fais qu'utiliser la ressource merci" ? Et que ça ne veut pas dire qu'il y aura la moindre fuite mémoire ? Comme par exemple [...]

              Dis moi que tu plaisantes... Ton expérience en C++ se résume à avoir regardé ses vidéos ?
              Pour découvrir ça faut vraiment pas avoir codé longtemps...


              Il n'y a pas vraiment de C++ dans ses vidéos, ce que je connais en C++ je l'ai appris par les sources officiels et des cours de C++17 à l'université. Ce que je veux dire c'est qu'on dit partout que les raw pointers sont mauvais alors qu'il expriment très bien cette sémantique, et il en va de même pour les fonctions, prendre un raw pointer veut dire qu'on se fiche de l'ownership (cf. http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-smart), bien qu'on puisse généralement passer une référence dans ce cas. D'ailleurs sur la question pointeur vs référence, on sait que les références pointent normalement vers un objet existant, mais est-ce que justement ça ne favoriserait pas les segfault ? (ça parait fou dit comme ça, mais regardez juste cet extrait : https://guide.handmadehero.org/chat/chat010/#85) 

              jo_link_noir a écrit:

              > D'ailleurs, la gestion moderne "haut-niveau" d'un sleep ressemble à ça en C++ :
              > > std::this_thread::sleep_for(std::chrono::milliseconds(100));
              > A comparer avec du code Windows "bas niveau" :
              > > Sleep(100);

              Le problème de la version C, -- en plus de ne pas être portable -- est propice aux erreurs.

              La portabilité est un non-problème quand le code est bien organisé et l'implémentation MSVC de cette fonctionnalité de la STL est buguée (https://developercommunity.visualstudio.com/t/bogus-stdthis-threadsleep-for-implementation/58530). C'est propice aux erreurs mais rien n'empêche de se faire une abstraction par dessus avec un truc comme std::chrono et les littéraux qui vont avec.

              CristianoRolando a écrit:

              J'ai lu vite fait le thread.

              Ma remarque est générale. Jade, tu défends Ryan Fleury ou Casey, je ne sais plus. Mais, as-tu regardé aussi attentivement ce qui se faisait ailleurs en C++ ?

              Si c'est ta seule référence, et que tu es impressionnée par leur travail, c'est normal que c'est bien pour toi. Pour comparer il faut 2 références au moins.

              Question pertinente, puisque c'est exactement ce que moi-même je vous reproche. Pour ma part, je connais mieux le C++ moderne que le "Caseylang", et comme je l'ai dit il m'a fallu le regarder pendant des centaines d'heures pour ne serait-ce qu'arrêter de penser "mais qu'est-ce qu'il fout ce mec, c'est dégueu, il aurait pu faire comme ci comme ça, avec telle ou telle fonctionnalité C++/STL"

              lmghs a écrit:

              > Le simple fait de déclarer un std::vector dans une fonction c'est déjà une grave erreur, et oui je croyais que c'était comme ça qui fallait faire et que le compilateur allait faire "sa magie" bah pas du tout, il se met vraiment à demander de la mémoire à l'OS et appeler des constructeurs de partout même quand c'est pas nécessaire

              Tu m'expliques la différence avec un malloc dans fonction?

              Pas de différence notable de mon point de vue, c'est tout aussi "dégueu", à comparer avec d'autres organisations du programme, etc, qui permettent de tout simplement ne pas faire d'allocation, mais je n'ai pas d'exemple concret à vous montrer, juste regardez HandmadeHero.

              lmghs a écrit:

              > Ce que je comprends en lisant ça c'est que vous le prenez de haut en ne considérant même pas la valeur pédagogique démentielle présente dans cette série (

              Du tout. On a juste une vie et nullement le temps de consulter autant de contenus non greppables.

              C'est bien le problème qui fait qu'on a du mal à se comprendre. Il y a tout de même un "guide des épisodes" avec des annotations minute par minute qu'on peut rechercher textuellement (https://hero.handmade.network/episode/code)

              lmghs a écrit:

              > heureusement qu’on a if constexpr maintenant

              C'est un total autre débat. Je suis très dubitatif sur le sujet. On abandonne l'OCP avec `if constexpr`. Alors c'est sûr que les spécialisations template c'est relou à écrire (c'est à peine mieux que le xslt AMA), mais du coup ces points de variation ne sont plus extensibles. D'où mon interrogation. C'est comme abandonner les fonctions virtuelles et revenir à 5 ifs en cascade à la place.

              Justement, au final, n'est-ce pas mieux d'avoir le code à un seul endroit plutôt qu'éparpillé dans toute la codebase ? Ajouter un cas se résumerait à ajouter du code dans le switch, et on peut voir d'un coup d'oeil tout ce qui peut se passer, sans aller chercher à droite à gauche. Casey a de solides arguments à ce sujet : https://guide.handmadehero.org/code/day349/#2412. D'ailleurs même Sir Lynix fait les choses à la Casey dans son parseur NZSL.

              • Partager sur Facebook
              • Partager sur Twitter
                26 septembre 2021 à 17:12:38

                "juste regardez HandmadeHero."
                Tu as d'autre argument ,que d'invoquer ton Dieu ?

                Oui parce que là sur chaqu'une de tes réponses,  ça peut se résumer : "regardé ce qu'il dit , j'ai eu la révélation" , mais j'avoue que le C++ est le seul langage où je peux voir un certain fanatisme.

                Bon courage dans ta nouvelle religion non-C++ ;)

                -
                Edité par HelbaSama 26 septembre 2021 à 17:18:17

                • Partager sur Facebook
                • Partager sur Twitter
                  26 septembre 2021 à 18:17:59

                  HelbaSama a écrit:

                  "juste regardez HandmadeHero."
                  Tu as d'autre argument ,que d'invoquer ton Dieu ?

                  Oui parce que là sur chaqu'une de tes réponses,  ça peut se résumer : "regardé ce qu'il dit , j'ai eu la révélation" , mais j'avoue que le C++ est le seul langage où je peux voir un certain fanatisme.

                  Bon courage dans ta nouvelle religion non-C++ ;)


                  J'aurai pensé qu'un contenu gratuit dispo sur Internet aurait forcément été vu et analysé publiquement par tout le monde mais apparemment ce n'est pas le cas, ce qui est dommage. J'essaie de linker des passages courts qui apportent des arguments. Encore une fois contrairement à vous je n'ai pas à défendre des décennies de pratique et d'habitude, ce qui fait que je suis pas biaisée. Je m'en fiche royalement du C++ tout comme je me fiche du C qui est encore pire. Je cherche juste dans l'absolu des méthodes de programmation, des façons de penser, qui permettent efficacement de résoudre des problèmes que l'on a en pratique.

                  michelbillaud a écrit:

                  Probleme, c'est délicat d'apprendre à s'en servir quand on a passé des années à programmer n'importe comment :-)

                  Mais on a toujours ce problème quand on change les paradigmes de programmation. Knuth a eu du mal à se mettre à la programmation structurée.

                  -
                  Edité par michelbillaud il y a environ 9 heures

                   Ca c'est un argument qui pourrait tenir la route à première vue. Evidemment que ça ne m'intéresse pas de suivre une voie ou autre aveuglément sans se poser de questions. S'il se trouve que Casey et les autres dont j'ai parlé sont tous mauvais (ce qui n'est déjà pas le cas au vu de leurs contributions) sous prétexte qu'ils n'ont "pas eu envie de se mettre à de nouvelles façons de faire", alors dans ce cas on pourrait se poser des questions sur la pertinence de leurs propos. Il se trouve que dans le cas de Casey, ce n'est pas ce qui se passe puisqu'il critique le C++ en connaissance de cause, pas comme certains qui ont juste eu la flemme de l'apprendre, et en plus il apporte des arguments insoupçonnés qui remettent en cause les pratiques modernes et leur utilité.

                  Finalement ma question originale était peut être un peu trop vulgaire mais en enlevant cette partie, on se rend compte que la réponse est effectivement comme je le craignais que vous n'avez pas rencontré ces façons de penser, qui je le répète ne sont pas juste du vieux C dégueu que vous utilisez comme exemple pour montrer que le C++ est mieux. C'est vraiment plus profond que ça. Après il n'y a pas que HandmadeHero qui fait les choses comme ça, d'ailleurs j'en avais pas même parlé au début, mais bon il faut regarder ce qui se fait et pas seulement ce qui va dans votre sens, tout le monde a a y gagner de regarder le "camp" d'en face pour voir si on peut pas en tirer des choses. Et surtout par pitié vous voyez bien que les logiciels modernes de Microsoft sont d'une calamité inégalée, dès qu'on fait trois traits dans Whiteboard ça commence à buguer (problème de perf) et quand on a un stylet et qu'on sélectionne un autre stylo, le précédent reste sélectionné ! (bug) et quand on fait ctrl+z il arrive des fois que ça ne soit pas le dernier trait qui s'efface, mais l'avant dernier ! (bug) et je parle pas de Visual Studio qui est juste inacceptable, cf la vidéo que j'ai linké plus haut où on voit VS tourner sur un Pentium 4 il y a 20 ans et qui est plus rapide que la version 2019, sur mon i9 11900k, non mais on en arrive à un point franchement.

                  Et vous dites aussi qu'il faut pas "réinventer la roue", mais de quelle roue parlez-vous ? Tout ce qu'on a aujourd'hui c'est des pneus crevés. D'ailleurs il y a la "Wheel Reinvention Jam" qui commence demain si ça intéresse quelqu'un de coder un logiciel qui pourrait faire mieux que ce qu'on a aujourd'hui (https://handmade.network/jam)
                  (je rappelle que le debugger RemedyBG a été codé par un mec sur son temps libre, et qui enterre VS (démo dans la même vidéo que j'ai linké))

                  • Partager sur Facebook
                  • Partager sur Twitter
                    26 septembre 2021 à 18:32:12

                    JadeSalina a écrit:

                    Finalement ma question originale était peut être un peu trop vulgaire mais en enlevant cette partie, on se rend compte que la réponse est effectivement comme je le craignais que vous n'avez pas rencontré ces façons de penser, qui je le répète ne sont pas juste du vieux C dégueu que vous utilisez comme exemple pour montrer que le C++ est mieux. C'est vraiment plus profond que ça. Après il n'y a pas que HandmadeHero qui fait les choses comme ça, d'ailleurs j'en avais pas même parlé au début, mais bon il faut regarder ce qui se fait et pas seulement ce qui va dans votre sens, tout le monde a a y gagner de regarder le "camp" d'en face pour voir si on peut pas en tirer des choses.


                    Bah , je le redis tu manque d'expérience et probablement ceux que tu encenses aussi , la programmation que tu dis me fait pensé a ce que j’appelais "programmation statique" ou programmation "worst case".
                    Donc qu'on fait un malloc , qu'on va au plus simple , qu'on ne gère pas 20000 cas complexes et donc tout ce que propose le C++ moderne est effectivement  "inutile" etc etc
                    Et c'est comme ça qu'on a programmé les JV jusqu’en 2000-2005 , qu'on y'a eu les gros jeux AAA qui sont arrivé, les japonais qui était vraiment expert dans la programmation que tu appelle "C sans les truc complexe du C++" ,ben étrangement , ils se sont tous cassé les dents :)
                    Pas pour rien quelqu'un ici à dit , que HH programme comme on le faisait , il y'a 20 ans , oui à l'époque de la PS2 , seul il aurait peut être fait mieux que EPIC , par contre il aurait mordu la poussière sur la gen suivante ;)

                    Franchement à la limite ta question qui aurait pu être "on n'envoie pas le bazooka un peu trop tôt en C++ ?" aurait plus de sens que de dire que tout ce que propose le C++ moderne est inutile.

                    -
                    Edité par HelbaSama 26 septembre 2021 à 19:09:37

                    • Partager sur Facebook
                    • Partager sur Twitter
                      26 septembre 2021 à 19:29:47

                      Salut,

                      JadeSalina a écrit:

                      Justement, au final, n'est-ce pas mieux d'avoir le code à un seul endroit plutôt qu'éparpillé dans toute la codebase ? Ajouter un cas se résumerait à ajouter du code dans le switch, et on peut voir d'un coup d'oeil tout ce qui peut se passer, sans aller chercher à droite à gauche. Casey a de solides arguments à ce sujet : https://guide.handmadehero.org/code/day349/#2412. D'ailleurs même Sir Lynix fait les choses à la Casey dans son parseur NZSL.

                      Hé bien tu  sais quoi? (car j'ai regardé l'extrêt que tu nous donne)

                      J'aurais pu être d'accord avec ce que ce mec dit... jusqu'à ce qu'il prétende (à partir du timestamp 11:34, pour être précis) qu'il est possible d'effectuer un test sur la validité du pointeur mais pas sur celle d'une référence.

                      Car, ce qu'il oublie de dire (outre le fait qu'il aurait du utiliser une assertion), c'est qu'il y a parfaitement moyen d'entourer l'appel de la fonction par le test.

                      Pour être clair: il présente d'abord deux fonctions:

                      void foo(int *a){
                          *a=5;
                      }
                      void foo(int & a){
                          a = 5;
                      }

                      Et il explique -- à  juste titre -- que ces deux fonctions vont fonctionner exactement de la même manière au niveau de l'exécutable final. Puis il nous présente l'appel de cette fonction avec entier dont on sait qu'il existe, sous la forme de

                      void b(){
                         int a=6;
                         foo(&a);
                      }
                         /* et pour les références */
                      void b(){
                         int a=6;
                         foo(a);
                      }

                      pour lesquels il nous dit qu'il n'y a pas de différence.  Et je dois admettre que, à ce niveau là, il a tout à fait raison.

                      Seulement, les choses partent en couille juste après... Et c'est parce que j'ai de l'expérience que je le remarque, alors que tu ne l'as sans doute pas remarqué, justement, parce que tu as clairement beaucoup moins d'expérience que moi (et ce n'est pas un reproche, c'est juste une constatation: l'expérience prend du temps à  s'acquérir ;) ).

                      Car ce brave monsieur commence à nous parler d'une autre situation qui serait l'utilisation d'un pointeur, et il nous présente donc les fonctions

                      void b(){
                          int * a = /* ? maybe NULL */;
                          /* ... */
                          foo(a);
                      }
                      /* et pour les références */
                      void b(){
                          int * a = /* ? maybe NULL */;
                          /* ... */
                          foo(*a);
                      }

                      Et il nous dit -- à juste titre -- que nous aurions pu ajouter un test dans la version avec un pointeur, sous une forme proche de

                      void foo(int * a){
                          if(a){ // j'aurais personnellement préféré une assertion
                                 // mais bon... qui suis-je face à ton guru???
                              *a=5;
                          }
                      }

                      Puis il nous dit que l'on ne pourra plus teste la validité du pointeur dans la version avec référence.

                      Et le pire, c'est qu'il a effectivement raison.

                      Seulement, ce qu'il oublie de préciser, c'est que si on veut travailler de manière sécurisée avec des pointeurs, on ne peut EN AUCUN CAS essayer de le déréférencer avant de s'être assuré de sa validité...  JAMAIS...

                      Or, le déréférencement du pointeur n'a pas lieu dans foo (pour la version avec référence) mais bien ... dans b.  Et c'est donc ... dans b qu'il faut s'assurer de la validité du pointeur

                      void b(){
                          int * a = /* ? maybe NULL */;
                          /* ... */
                          if(a){
                              foo(*a);
                          }
                      }

                      Vois tu le biais dans ses explications?

                      Maintenant, peut-être as tu remarqué le commentaire que j'ai ajouté dans la version avec un pointeur...

                      En effet, j'aurais préféré une assertion car cette vérification a pour but de repérer les erreurs de programmations: si on appelle foo, on ne peut pas transmettre de pointeur null à la fonction.  Si c'est le cas, c'est qu'il y a "une vérification" que l'appelant n'a pas pensé à faire.

                      Et donc, je préférerais un code proche de

                      void foo(int * a){
                          assert(a && "null pointer detected");
                          *a = 5;
                      }

                      Car, à partir du moment où toutes les fonctions qui font appel à foo pensent effectivement à s'assurer de la validité du pointeur -- ce qui sera normalement le cas en production ... du moins, s'il y a une politique correcte de tests -- la vérification à l'intérieur de la fonction n'aura tout simplement plus de raison d'être.

                      En outre, pour bien enfoncer le clou quant aux explications, je vais m'amuser à complexifier encore un peu son exemple...

                      Mettons que l'on ait un code pour b proche de

                      void b(){
                          int * a = new int; // le pointeur  est valide
                          /* ... */
                          delete a; // CRACK: l'adresse semble valide, mais elle ne l'est plus
                          /* Pour éviter tout problème, il aurait fallu redonner la 
                           * seule valeur testable à a: nullptr
                           * je fais exprès de ne pas le faire ici, car le delete 
                           * aurait pu être fait "ailleurs", sans que l'adresse
                           * représentée par a ne soit modifiée
                           */
                           foo(a); // BOUM: même en testant le pointeur  dans foo,
                                   // on ne peut pas se rendre compte qu'il est invalide
                      }

                      Je ne vais pas écrire le code correspondant pour la version par référence, car, de fait, le problème sera exactement le même: on essaye d'accéder à  "ce qui se trouve à une adresse" qui ne contient quoi qu'il arrive pas ce que l'on espère.

                      Seulement, ce monsieur n'aborde pas ce problème, et il présente -- de manière biaisée en fait -- l'utilisation des références comme une approche ne présentant aucune tolérance aux erreurs, et l'utilisation des pointeurs comme une utilisation présentant, au contraire, une grande tolérance aux erreurs.

                      Alors, soyons bien clair: il n'est pas dans mes intentions de remettre en cause la compétence de ce monsieur, que je ne connais absolument pas (et, pour tout dire, je n'ai ni le temps ni le courage de me taper 250 video pour m'en faire une idée), ni même de casser du sucre sur son dos, ce qui ne serait pas très fair-play, vu qu'il ne viendra surement pas défendre son point de vue ici.

                      Seulement, je ne peux m'empêcher de remarquer qu'il n'a peut-être pas été "au bout de sa réflexion" sur ce point particulier, et donc, que son point de vue est "quelque peu biaisé".

                      Et, bien sur, comme tu manque d'expérience, il est "tout à fait normal" que tu ne l'ai pas forcément remarqué par toi-même.

                      Cependant, tu nous demande depuis le début de cette discussion de nous remettre en question.  Je viens de t'apporter la preuve que j'ai regardé au moins une video sans parti pris et dans la ferme intention de me remettre en question si les arguments cités me convainquaient.

                      La question est donc "seras-tu toi aussi capable de te remettre en question, face aux arguments que j'ai apporté?"

                      • 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
                        26 septembre 2021 à 19:29:54

                        En préambule, je commencerais par dire que je ne suis pas particulièrement développeur C ou C++ ; j'ai pratiqué les 2 langages mais je ne me définirais ni comme un développeur C expérimenté ni comme un développeur C++ expérimenté (a fortiori du C++ "moderne")

                        Ce qui m'interpelle, c'est que tout ton argumentaire suit une logique spécieuse

                        JadeSalina a écrit:

                        J'aurai pensé qu'un contenu gratuit dispo sur Internet aurait forcément été vu et analysé publiquement par tout le monde mais apparemment ce n'est pas le cas, ce qui est dommage.

                        Pourquoi ? ou comment même ? pour ne citer qu'un exemple Wikipédia est gratuit, tout le monde l'a lu ?

                        Je ne dis pas que ce n'est pas une ressource potentiellement intéressante (note, non je ne suis pas allé voir ; c'est pas mes langages et j'aurais pas le level) mais ça ne doit pas être la seule.

                        Sauf que tu ne cites quasiment que celle là ; là où d'autres citent des ressources multiples (que je n'ai pas plus été voir) et c'est un des soucis pour moi ; tu le places comme un argument d'autorité ou comme une référence ; en tout cas c'est l'impression que ça donne.

                        JadeSalina a écrit:

                        Encore une fois contrairement à vous je n'ai pas à défendre des décennies de pratique et d'habitude, ce qui fait que je suis pas biaisée.

                        Bien sûr que si, comme tout le monde ; tu peux dire que les "bagages" que d'autres ont ne t'influencent pas, pourquoi pas. Mais tu en as d'autres, comme celui de rester sur cette seule source d'information comme référence (et là je ne dis pas si elle est bonne ou mauvaise) ; mais c'est un biais tout autant.

                        JadeSalina a écrit:

                        Je cherche juste dans l'absolu des méthodes de programmation, des façons de penser, qui permettent efficacement de résoudre des problèmes que l'on a en pratique.

                        C'est une intention louable ; mais il y a souvent plusieurs méthodes pour un seul problème ; parfois chacune avec ses avantages ou inconvénients.

                        Oui ce sont des platitudes évidentes que je débite là ; parce qu'il est vain de chercher LA réponse ultime à tout ; mais pour ça il faudrait évoquer des problèmes précis dans des contextes précis, avec des biais (pas [forcément] humain, biais technique, biais historique, biais commercial) pour y apporter des réponses au cas par cas.

                        Après le débat "philosophique" a son charme ^^

                        JadeSalina a écrit:

                        S'il se trouve que Casey et les autres dont j'ai parlé sont tous mauvais (ce qui n'est déjà pas le cas au vu de leurs contributions) sous prétexte qu'ils n'ont "pas eu envie de se mettre à de nouvelles façons de faire", alors dans ce cas on pourrait se poser des questions sur la pertinence de leurs propos.

                        Alors cette phrase "démarrait bien" (désolé c'est un jugement subjectif et forcément biaisé là) mais je n'en comprends pas la logique. Pourquoi ça ne serait pas le cas au vu de leurs contributions, moi qui suit à des lieux de tout ce sujet, je ne vois pas l'argumentaire qui le justifie.

                        Et tu ne peux pas rétorquer un "il suffit d'aller voir les vidéos" ; si tu dis qu'il y a un biais chez ceux à qui tu demandes de regarder, il faudrait peut-être que tu apportes ton éclairage personnel, que l'on puisse cerner ton point de vue (il ne se résume pas à "regardez les vidéos" ou "lisez les articles" ?)

                        C'est peut-être là que ça coince, apporter ton propre cheminement de pensée, plus qu'un discours de zélote en mission pourrait peut-être aider à cet "échange" ?

                        Par extension, je ne comprends donc pas non l'argumentaire (plus précisément je ne le vois pas) qui justifie que l'on ne pourrait pas se questionner sur la pertinence de leurs propos

                        C'est d'ailleurs intéressant, je trouve ; d'un côté tu dis que les gens ne se remettent pas en question sur leurs pratiques ; et de l'autre tu dis qu'on a pas de raison de remettre en question les pratiques de ta source principale. ça fait un peu faites comme je dis pas comme je fais, ce qui encore une fois ne facilite pas "l'échange" le faisant paraitre obtus, fermé et immuable quant aux conclusions

                        JadeSalina a écrit:

                        Finalement ma question originale était peut être un peu trop vulgaire mais en enlevant cette partie, on se rend compte que la réponse est effectivement comme je le craignais que vous n'avez pas rencontré ces façons de penser, qui je le répète ne sont pas juste du vieux C dégueu que vous utilisez comme exemple pour montrer que le C++ est mieux.

                        C'est une des choses que j'ai beaucoup lu dans ce sujet ; les "qui ne sont pas" ; mais du coup, moi personne extérieure, je ne sais pas vraiment "ce qui est" ; et l'argument de devoir aller chercher soi-même, est au mieux non-pédagogique, un comble pour quelqu'un qui espère faire bouger des lignes.

                        La fin, dénonce le fait qu'on utilise de mauvais exemple de C pour justifier le C++. Oui ça doit exister, mais c'est une généralisation peut-être un peu trop facile aussi. Tu utilises bien quasi exclusivement une seule source pour justifier ton argumentaire (sans vraiment justifier à part dire regardez) là où si j'ai suivi ce qu'on y rétorque ce n'est pas en adéquation avec des problématiques réelles et concrètes du quotidien

                        Moi ce que j'en comprends, c'est que personne n'a dit que c'était fondamentalement mauvais, juste voir dans quel cadre ça s'applique ; là où toi tu rejettes dans l'ensemble tout ce qui n'est pas "ça" ; c'est très excluant pour un discours qui se veut basé sur l'analyse de l'existant.

                        JadeSalina a écrit:

                        Après il n'y a pas que HandmadeHero qui fait les choses comme ça, d'ailleurs j'en avais pas même parlé au début, mais bon il faut regarder ce qui se fait et pas seulement ce qui va dans votre sens, tout le monde a a y gagner de regarder le "camp" d'en face pour voir si on peut pas en tirer des choses.

                        Avec ce passage là, je vois déjà arriver les phrases du type "commence par appliquer ton propre conseil" ; de quoi figer et cristalliser encore plus cet "échange"

                        JadeSalina a écrit:

                        Et surtout par pitié vous voyez bien que les logiciels modernes de Microsoft sont d'une calamité inégalée, dès qu'on fait trois traits dans Whiteboard ça commence à buguer (problème de perf) et quand on a un stylet et qu'on sélectionne un autre stylo, le précédent reste sélectionné ! (bug) et quand on fait ctrl+z il arrive des fois que ça ne soit pas le dernier trait qui s'efface, mais l'avant dernier ! (bug) et je parle pas de Visual Studio qui est juste inacceptable, cf la vidéo que j'ai linké plus haut où on voit VS tourner sur un Pentium 4 il y a 20 ans et qui est plus rapide que la version 2019, sur mon i9 11900k, non mais on en arrive à un point franchement.

                        Et vous dites aussi qu'il faut pas "réinventer la roue", mais de quelle roue parlez-vous ? Tout ce qu'on a aujourd'hui c'est des pneus crevés. D'ailleurs il y a la "Wheel Reinvention Jam" qui commence demain si ça intéresse quelqu'un de coder un logiciel qui pourrait faire mieux que ce qu'on a aujourd'hui (https://handmade.network/jam)
                        (je rappelle que le debugger RemedyBG a été codé par un mec sur son temps libre, et qui enterre VS (démo dans la même vidéo que j'ai linké))

                        Alors tout ce passage là ; je suis largué, je vois pas le rapport entre comment sont codés certains softs, et le fait que ça veut dire que tu as plus raison, ou plus tort d'ailleurs. Ensuite un VS d'il y a 20 et un VS2019 ne font pas la même chose ; ce type de test n'a que très peu de pertinence ; ça serait comme comparer le coût de la vie il y a 50 ans et aujourd'hui sans tenir compte de l'inflation (petit aparté là ; si je fais un test sur un i9 ou pour biaiser, je fais tourner le truc que sur 1 seul coeur ? je ne dis pas que c'est le cas ; mais j'ai appris à ne pas prendre pour argent comptant les choses, mais ça veut pas dire que la vidéo en question est dans ce scenario, je l'ai pas regardée ^^)

                        En conclusion, et ça sera mon avis très personnel et très biaisé, pour moi ; tu sonnes comme quelqu'un qui rage et peste contre des choses, et secoue des moulins à vent parce que personne ne voit ce que lui a vu. Et outre, la perte de temps généralisée, et l'augmentation de la "tension" pour ceux qui prendraient ça trop à coeur, c'est dommage ; parce qu'au milieu de tout ça il y a peut-être des choses intéressantes et constructives des 2 côtés

                        Je vais terminer là dessus, pour tout le monde, d'une manière générale, ça sert à rien de chercher à convaincre les autres qu'ils ont tort, ou chercher à convaincre les autres qu'on a raison ; déjà parfois raison/tort c'est fluctuant ; souvent c'est subjectif ou contextuel et surtout une explication est plus efficace à mes yeux, la différence entre une explication et un argumentaire : le premier est bienveillant et pédagogique, le second est pédant et démagogique (et oui pas de bol tout ça c'est des notions fluctuantes, subjectives et contextuelles aussi)

                        Bonne suite à tous dans la continuité de cet "échange" : ;)

                        • Partager sur Facebook
                        • Partager sur Twitter
                        Censément, quelqu'un de sensé est censé s'exprimer sensément.
                          26 septembre 2021 à 20:53:11

                          > écrire du code templaté illisible parce que le langage ne permet pas d'exécuter du code arbitraire à la compilation ?

                          https://en.cppreference.com/w/cpp/language/consteval

                          • Partager sur Facebook
                          • Partager sur Twitter
                            27 septembre 2021 à 0:18:35

                            > Ce que je veux dire c'est qu'on dit partout que les raw pointers sont mauvais alors qu'il expriment très bien cette sémantique, et il en va de même pour les fonctions, prendre un raw pointer veut dire qu'on se fiche de l'ownership (cf. http://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rf-smart)

                            Il y a un élément intéressant ici. Tu as la chance d'avoir probablement eu un bon cours de C++. Si si. Tu n'as pas idée de la quantité de ressources exécrables et du "combat" que l'on tient depuis plus de 2 décennies.

                            Cette parenthèse pour dire que cette règle des C++CoreGuideline n'est valable que dans un environnement où tous les développeurs ont été bien formés. Il existe encore beaucoup de code qui traine où un pointeur ça peut être tout et n'importe quoi. Un handle observateur, un handle responsable, qui en plus peut être ou non nul, peut modéliser ou non une nature optionnelle, ça peut être un handle vers n'importe quoi ou de la mémoire, voire vers un élément dans un tableau d'éléments, etc. Dans un vrai environnement industriel, au vu des profils hétérogènes des cours suivis, des participants aux projets, il n'est pas possible d'être sûr qu'un pointeur ne modélise que du non-responsable.

                            Bref, une règle intéressante mais encore utopique. Je préfère forcer la main avec références, unique_ptr, not_null, observer_ptr, optional, string_view, span, etc. Cela lève tout doute sur ce qui est possible de faire avec un pointeur.

                            > vlog sur les références VS pointeurs

                            Merci pour le lien. Je rejoins Koala ici. Si on passe un pointeur à une fonction qui attend une référence ou un pointeur non nul, le problème sera exactement le même. Des jolis UBs, et un code asm probablement identique. On en revient à la programmation par contrat, la fonction a une précondition: pointeur non null, ou référence valide. Pointeur c'est un contrat au niveau codeur, référence valide, c'est au niveau langage: le comportement d'un code qui manipule des références ne sera définit que si la référence est attachée vers quelque chose qui a un emplacement en RAM et qui reste valide. Autrement c'est UB, et ce qui est observé peut être bien différent de la "hard fault" décrite dans la vidéo.

                            Et ce n'est pas entièrement vrai pour le pas de warning sur ìnt *b =nullptr; foo(*b);`: https://godbolt.org/z/5dqncf9ob tidy le voit, clang avec l'extension lifetime aussi, et il me semblait que VC++ avait cela aussi. Bref, il faut s'outiller.

                            L'avantage de la référence est double.

                            1. sur le plan sémantique, pas besoin de de lire la doc pour savoir que l'on attend quelque chose qui n'est pas "null". Pas le moindre doute n'est possible si on mélange des développeurs d'horizons différents, même si la règle des C++CoreGuideline est imposée.

                            2. La première fonction qui prend une référence agit comme une frontière. Le développeur qui passe un machin accédé au travers d'un pointeur doit à ce moment là assurer que l'adresse est non nulle. Et une fois que l'on a passé la frontière on gagne l'invariant: "le machin derrière la référence est censé être valide". Certes il peut y avoir les soucis que la donnée cesse d’exister entre temps, mais pointeur ou référence ne changerait rien ici.

                            Cette garantie signifie que l'on peut alors se passer d'assert dans les fonctions en question ou de programmation défensive. Et du coup, on retrouve des perf grâce aux références, cf cette video dont j'ai parlé déjà de Bartosz Szurgot au c++ dive. Je donne le lien car je te sens autant fainéante que nous pour rechercher les infos (https://www.youtube.com/watch?v=PDSvjwJ2M80 ). Ici il vend plutôt not_null qui offre un intermédiaire entre la référence et la critique de Casey: on peut forcer une précondition au niveau code (et non langage) qui pourra être vérifiée avec assert.

                            Après on peut aussi discuter philo sur la fault-tolerance. Mon avis sur la question: "errors are not recoverable". Dans un article où il décrit son langage, Joe Duffy a tout un chapitre sur la question. Bref, je suis pour la simplification des codes des libs et remonter les vérifications au niveau des responsables: dans le cas des préconditions, c'est aux appelants de respecter les contrats.

                            > J'aurai pensé qu'un contenu gratuit dispo sur Internet aurait forcément été vu et analysé publiquement par tout le monde mais apparemment ce n'est pas le cas, ce qui est dommage.

                            Je te retourne la question. As-tu analysé Dan Saks? (et bien d'autres)

                            > Justement, au final, n'est-ce pas mieux d'avoir le code à un seul endroit plutôt qu'éparpillé dans toute la codebase ? Ajouter un cas se résumerait à ajouter du code dans le switch, et on peut voir d'un coup d'oeil tout ce qui peut se passer, sans aller chercher à droite à gauche. Casey a de solides arguments à ce sujet : https://guide.handmadehero.org/code/day349/#2412. D'ailleurs même Sir Lynix fait les choses à la Casey dans son parseur NZSL.

                            Autre sujet intéressant. Le tracing. C'est à dire le temps que l'on va mettre à comprendre ce que fait quelque chose. C'est généralement une question d'équilibre entre divers points: connaissance d'un référentiel standard (comme la SL p.ex.), DRY par factorisation de code commun. Concernant les points de variations, c'est une question des possibilités d'évolution que l'on peut attendre. Je te renvoie à mon exemple des balais et aspirateurs repris dans le tuto de ZdS. Ici avoir 3 switchs en fonction de la nature d'un éléments, c'est contre productif. Dans le cas d'une machine à états, même s'il y a un tel exemple dans le GoF à se sujet, c'est pour moi un domaine où le switch est parfait. Voire, on va parfois générer automatiquement cette machine à états depuis une terminologie en UML/réseau de pétri/lex|yacc/etc

                            > J'essaie de linker des passages courts qui apportent des arguments. Encore une fois contrairement à vous je n'ai pas à défendre des décennies de pratique et d'habitude, ce qui fait que je suis pas biaisée

                            Contrairement à nous tu n'as pas eu à te battre contre des décennies de pratiques exécrables qui ont conduit à un équilibre safe avec le RAII. D'abord on écrit un code stable, et de préférence maintenable qui répond au besoin exprimé, et après on optimise.

                            > les logiciels modernes de Microsoft sont d'une calamité inégalée, dès qu'on fait trois traits dans Whiteboard ça commence à buguer

                            Plus un soft est complexe, produit à la va vite, etc, plus il va y avoir des bugs. Peu importe le soft. Les bugs les plus pénibles en C++ (à supposer que le soft en question ne soit pas en C#...) c'est la gestion de la mémoire. Ou pourquoi on insiste sur RAII & cie. Pourquoi on insiste qu'il faut prendre en compte les possibles erreurs, etc.

                            -
                            Edité par lmghs 27 septembre 2021 à 0:23:37

                            • Partager sur Facebook
                            • Partager sur Twitter
                            C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                              27 septembre 2021 à 16:35:04

                              Dans la vidéo de code::dive (https://www.youtube.com/watch?v=PDSvjwJ2M80), il dit que le code C++ est plus rapide de 3% que la version C, mais j'ai comparé les deux versions sur compiler explorer (https://godbolt.org/z/d6aTK8zfc) et ce que je vois c'est que les deux versions ont exactement le même assembleur (à malloc/new près), donc les 3% de gain je ne sais pas d'où ils sortent. Ensuite il dit que la version STL permet d'avoir une abstraction qui fait que le compilateur comprend qu'on veut "fill" le vecteur et "accumulate", mais c'est faux ? Le compilateur ne comprend pas la sémantique des fonctions si ? Le compilateur ne voit que du code et dans ce cas, les deux versions sont tout aussi mauvaises l'une que l'autre. Le problème est que le fait de penser le code comme un enchaînement d'opérations prédéfinies, fait qu'on oublie comment écrire le code simplement ! Par exemple, qui aurait l'idée de faire deux boucles distinctes alors qu'on peut trivialement les regrouper ? La version STL impose ces boucles puisqu'on appelle directement les fonctions qui font précisément ces deux boucles, alors que sans penser de façon abstraite, on regroupe les deux boucles et devinez quoi ? Le compilateur a été capable de comprendre (version 3 dans godbolt) que toute l'accumulation suivie du modulo 256 revient à renvoyer directement 42, et ainsi la deuxième boucle disparaît complètement par la magie de l'optimisation ! Et ça ne s'est pas produit dans la version STL, puisque la structure même du code sous-entend qu'il y a deux boucles. Sinon oui la version STL génère le même code que le premier, mais ce code n'est pas vraiment ce qu'on aurait écrit en C en pensant sans "abstractions". Du coup je me demande si on peut vraiment faire confiance aux compilateurs pour optimiser...

                              Aussi il parle des génériques et compare la taille des exécutables, mais les deux tests ne sont pas équitables puisque dans le cas du C il appelle une macro qui va dupliquer le code du calcul de la médiane pour chaque appel, alors que dans la version template ça appelle des fonctions. On aurait pu avoir une macro à qui on passe le type et qui "génère" les fonctions, et ainsi ne pas avoir la taille de l'exécutable qui augmente,  mais là c'est vrai que les templates permettent de faire ça plus proprement.

                              Après je m'appelle pas Casey, j'ai juste découvert sa façon de faire et je me suis dit que ça avait l'air mieux que de sortir l'artillerie lourde du C++ moderne, mais j'ai moi même pas l'expérience sur de gros projets, etc. Mais le pire dans l'histoire c'est que Casey saurait probablement répondre à tout ça en apportant des solutions et des visions révolutionnaires. Par exemple vous allez me dire que ce style de programmation ne marche que si on est tout seul etc, mais il explique que ça marche aussi pour les gros projets (https://guide.handmadehero.org/code/day027/#4490) (ce qu'il appelle "compression oriented programming" c'est ce qu'il explique ici https://caseymuratori.com/blog_0015)

                              • Partager sur Facebook
                              • Partager sur Twitter
                                27 septembre 2021 à 18:06:22

                                JadeSalina a écrit:

                                il dit que la version STL permet d'avoir une abstraction qui fait que le compilateur comprend qu'on veut "fill" le vecteur et "accumulate", mais c'est faux ? Le compilateur ne comprend pas la sémantique des fonctions si ?

                                Ce qui s'appelait STL est maintenant (à peu près) une partie de la bibliothèque standard C++, et donc le compilateur peut utiliser des connaissances spécifiques sur les fonctions standard qu'on appelle (*)

                                Un exemple bête, on pourrait déduire que

                                std::cout << "";
                                

                                peut être éliminé.


                                (*) tout comme en C, les compilateurs se permettent d'aller regarder la chaine littérale donnée en premier paramètre de printf pour râler qu'on s'est planté dans les formats




                                -
                                Edité par michelbillaud 27 septembre 2021 à 18:14:37

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  27 septembre 2021 à 18:24:57

                                  "Le compilateur a été capable de comprendre (version 3 dans godbolt) que toute l'accumulation suivie du modulo 256 revient à renvoyer directement 42, et ainsi la deuxième boucle disparaît complètement par la magie de l'optimisation ! Et ça ne s'est pas produit dans la version STL, puisque la structure même du code sous-entend qu'il y a deux boucles. Sinon oui la version STL génère le même code que le premier, mais ce code n'est pas vraiment ce qu'on aurait écrit en C en pensant sans "abstractions". Du coup je me demande si on peut vraiment faire confiance aux compilateurs pour optimiser..."

                                  Cette optimisation est biaisé , dans le sens où , les deux autre semble plus "réalise" , que le troisième qui est complètement absurde :)
                                  Oui le compilo devine que dans le 3eme cas que le résultat fait 42 , donc que le résultat est connu à la compilation , les deux autre ,on empêche le compilo de faire cela.
                                  Mais le troisième cas est idiot , parce que dans 99.9999% des cas  ,on ne connaît pas justement l’ensemble des valeurs à l’exécution ! :D
                                  (sauf quand tu fait un truc du genre a = b + 42*5 où on peut precalculé une partie par exemple).

                                  Donc pour résumer : "Du coup je me demande si on peut vraiment faire confiance aux compilateurs pour optimiser..."
                                  Clairement  oui sauf sur certain cas , mais pas sur les cas montré , et ce sont des  cas que je connais relativement bien , vu que j'utilise souvent des cas 1 et 2 pour éviter qu'il optimise trop , comme dans un cas 3 où on met toute les valeur on dure avec un code trop simple (et pas super réaliste au final) et on ne peut pas voir comment le compilo travaille vraiment.


                                  "Aussi il parle des génériques et compare la taille des exécutables, mais les deux tests ne sont pas équitables puisque dans le cas du C il appelle une macro qui va dupliquer le code du calcul de la médiane pour chaque appel, alors que dans la version template ça appelle des fonctions. On aurait pu avoir une macro à qui on passe le type et qui "génère" les fonctions, et ainsi ne pas avoir la taille de l'exécutable qui augmente,  mais là c'est vrai que les templates permettent de faire ça plus proprement."
                                  Si le mec compare la taille des exécutables pour savoir qui est le plus efficace ,c'est qu'il est encore plus hors du coup que je le pensais...
                                  Je mettrais pas ici le pourquoi du comment, mais l'analyse de l'optimisation d'un x86 , c'est pas "oui je regarde le code ,je regarde ce qui fait le moins et le plus petit , c'est le plus optimisé" , le x86 est ultra complexe et ça demande des connaissances sacrément pointu en micro architecture  pour lire un code x86 et savoir qui est le plus optimisé , le mieux et le plus facile et rapide à faire , et une mesure réel à l'exécution.
                                  Et franchement l'analyse du code asm ,  on peut pas réellement juger (je parle de ton cas) , si tu sais pas programmer en asm  ,le but est de regarder ,de voir ce que fait le compilo et si c'est ce que t'aurais fait en asm  , voir qu'il fait mieux que ce que t'aurais fait en asm ,  que tu peux là dire si compilo C ou C++ est correct où non.
                                  Le truc c'est que le compilo , il a la doc intel sous les yeux et les recommandations d'optimisations ,alors que toi non ;)

                                  "des solutions et des visions révolutionnaires"
                                  Pour le moment , j'ai rien vu de révolutionnaires sur ce qu'il fait ou dit pour le moment :)

                                  pour le lien , je vais pas tout quote , mais grosso modo la programmation compressé qu'il appelle , où qui se résume par :
                                  "My mantra is, “make your code usable before you try to make it reusable”."

                                  Et ce que je disais juste avant sur la programmation statique , ça veut dire qu'on fait le minimun de code sur un shema qu'on connaît à l'avance (et donc difficilement réutilisable , vu que c'est pour sur un shema bien précis).
                                  Et donc ça n'a rien de révolutionnaire, vu que c'est comment on programmait avant (pour des raisons de perf tout simplement) , et oui , ça a des avantages (et inconvénient) de programmé comme ça.
                                  Et je le redis ,tu ne fera jamais avec cette méthode Unreal Engine :)
                                  Après c'est pas un soucis , en tant que débutant ,tu le fera jamais et donc utilisé une méthode qui te simplifie la vie pourquoi pas.
                                  Mais faut dire que les besoins actuel et les algo de plus en plus complexe et les habitudes utilisateurs , font en sorte que à part faire du JV indé ou quelque tools , cette méthode me semble bien restreindre pour l'appliqué totalement.
                                  Et donc je ne vois rien d'aberrant qu'on t'enseigne tout le C++ et la sécurité  du code qui va avec , ben parce que tu vas pas forcément tombé dans un cas ou méthode d'il y'a 20 ans :)

                                  Je suis obligé de quote :
                                  "I like to think of efficiency as holistically as possible. If you look at the development process for a piece of code as a whole, you won’t overlook any hidden costs. Given a certain level of performance and quality required by the places the code gets used, beginning at its inception and ending with the last time the code is ever used by anyone for any reason, the goal is to minimize the amount of human effort it cost. This includes the time to type it in. It includes the time to debug it. It includes the time to modify it. It includes the time to adapt it for other uses. It includes any work done to other code to get it to work with this code that perhaps wouldn’t have been necessary if the code were written differently. All work on the code for its entire usable lifetime is included."

                                  C'est là que je me dis qu'il manque d'expérience ,ou qu'il a fait que du JV indé ou non AAA.
                                  C'est beau , faut faire au plus simple , simplifier le code etc etc , tout le monde est d'accord avec ça.
                                  Mais ça marche pas toujours comme ça , quelque fois la complexité est insoluble et donc cette merveilleuse philosophie de simplifier le code à son extrême ne marchera pas.
                                  Tu sera obligé de sortir le bazooka , et de donner une solution complexe et un code non simple à écrire.
                                  Apres si c'est juste un conseil au débutant de dire "arrêter de faire trop complexe" , là oui , je suis d’accord, les débutants ont tendance à complexifier des problemes relativement simples.

                                  -
                                  Edité par HelbaSama 27 septembre 2021 à 18:39:47

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    27 septembre 2021 à 19:02:14

                                    HelbaSama, JadeSalina citait la vidéo de Bartosz Szurgot au C++ Dive. Il décrit précisément les compilos avec lesquels il a fait ses analyses. Quant à l'analyse des tailles, c'est parce qu'il fait de l'embarqué et qu'il s'attaquait à certains préjugés.

                                    Je répondrais plus proprement plus tard -- notamment splitter 1 boucle en deux a parfois énormément de sens en optim quand le compilo ne sait pas splitter lui même et/ou vectoriser ; son compilo était plus ancien, etc . Et effectivement, pour bien faire, il faudrait sur godbolt juste la fonction test (pas de main), qui prend en paramètres les trucs mis en dur comme le 3.

                                    -
                                    Edité par lmghs 27 septembre 2021 à 19:02:38

                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                    C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                      27 septembre 2021 à 21:08:22

                                      HelbaSama a écrit:

                                      C'est là que je me dis qu'il manque d'expérience ,ou qu'il a fait que du JV indé ou non AAA.

                                      A mon avis, la base du problème est là. Quand on pose la question de savoir si on peut mieux optimiser que le compilo, la réponse est "oui, parfois". Mais quand on prend du recul :

                                      - plus le projet est de taille conséquente, plus cela devient difficile de faire des optis manuelles (ou tout au moins, cela a un coût de développement conséquent)

                                      - le compilo peut faire des optis dans pleins de domaines (cache, vectorisation, etc)

                                      - il faut avoir les compétences dans tous ces domaines (CPU et GPU)

                                      - et surtout, il faut que ces optis ont un sens, c'est à dire que la différence de performances justifie le coût de développement

                                      Au final, la question n'est pas pertinente, parce que dans tous les cas, on est obligé de faire confiance aux compilos. Et d'optimiser que ce qui est pertinent.

                                      -----------------------------------------------------------

                                      Et pour son article de blog, je rejoins Helba. Ca se voit qu'il ne sait pas trop de quoi il parle et c'est pour ca qu'il a une approche complètement naïve.

                                      Par exemple, dans son article sur la POO, il critique le fait qu'il est difficile de composer des objets à partir d'un héritage avec un god object (en prenant l'exemple d'une classe de base Personne...). Bien sur qu'on va être d'accord avec cette critique ! On n'arrête pas de faire la même sur le cours de C++ de OC.

                                      Mais la POO, c'est pas que cette approche. Il y en a pleins, avec des classes de composants, des approches data driven (dont l'ECS dont a parlé lmghs), etc. Il rejette la POO juste parce qu'il ne connaît pas toutes ces méthodes et surtout parce qu'il croit que le peu qu'il connaît est suffisant pour rejeter la POO. Il montre juste son incompetence. (Et bien sur que la POO est critiquable. Mais utile aussi. Encore faut il connaître le sujet pour savoir comment l'utiliser correctement)

                                      Son exemple avec le layout est juste consternant de naïveté. Croire que c'est "révolutionnaire" alors que ca a juste 20 ans de retard...

                                      -
                                      Edité par gbdivers 27 septembre 2021 à 21:09:03

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        28 septembre 2021 à 1:44:03

                                        > donc les 3% de gain je ne sais pas d'où ils sortent.

                                        Je vois deux hypothèses:
                                        - Les tests avaient été faits avec un compilo plus ancien
                                        - Il suffit que les codes ne soient pas exécutés depuis le m^eme répertoire pour impacter les performances -- si si, les variables d'environnements peuvent impacter les perfs

                                        > Le compilateur ne comprend pas la sémantique des fonctions si ?

                                        Ca s'est déjà vu (genre memcpy pour le type puning). Ou à l'inverse, il transforme une boucle en un ou deux appels à memcpy/memset. Ici, le code ne donne pas cette impression car je ne vois qu'un seul memset au lieu de 2 (pour le vecteur il y a un premier memset sur le constructeur). Quoiqu'on dirait bien qu'il a mergé le fill avec le constructeur en virant le memset à 0. C'est fort. Il ne savait pas faire il y a quelques années.

                                        > Le problème est que le fait de penser le code comme un enchaînement d'opérations prédéfinies, fait qu'on oublie comment écrire le code simplement

                                        C'est sur que si on réfléchit, nul besoin de boucle ni rien: 2000000*k%256, ça fera toujours 0. Le fait qu'il y ait deux boucles empêche le compilo de fusionner, j'avoue ne pas voir ce qui le bloque vu que les tableaux sont locaux sans possible interaction depuis l'extérieur, dans un autre thread typiquement.

                                        > Par exemple, qui aurait l'idée de faire deux boucles distinctes alors qu'on peut trivialement les regrouper ?

                                        Moi le premier, et plein d'autres qui ont un peu eu à optimiser. Le compilo sait parfois optimiser, mais ce n'est pas toujours le cas. Je l'ai déjà vu splitter une boucle en plusieurs qui devenaient à leur tour des appels à memset ou memcpy: https://godbolt.org/z/qf3v5v7K6 Pareil, pour une meilleure vectorisation il est parfois plus intéressant de splitter des boucles.

                                        > Le compilateur a été capable de comprendre (version 3 dans godbolt) que toute l'accumulation suivie du modulo 256 revient à renvoyer directement 42, et ainsi la deuxième boucle disparaît complètement par la magie de l'optimisation !

                                        Et peut-être que dans 2 ans les compilos verront que le tableau ne servait à rien... Dans tous les cas, cela ne doit pas nous empêcher de réfléchir. Et +1 à ce que dit HelbaSama. En général, on va remplir le vecteur avec un truc relativement complexe et si on réalise l'accumulation à la volée on risque d’empêcher toute vectorisation. Et encore, en amont on se demandera alors si on a bien besoin du tableau. Si oui, 2 passes seront bien possiblement plus efficaces sur les archis classiques (avec les bons flags de compil comme -Ofast ou -march). Mais... à bencher!

                                        ------------

                                        (et là je commence à râler après le forum du sdz/oc pour les citations...)

                                        HelbaSama a écrit:<<Si le mec compare la taille des exécutables pour savoir qui est le plus efficace ,c'est qu'il est encore plus hors du coup que je le pensais...>>

                                        Comme je le disais, Bartosz Szurgot est sur des archis embarquées et visiblement pour lui soit ça fait sens, soit (plus probablement), il adressait les critiques de la communauté C comme quoi le C++ produit des binaires trop gros qui sont inacceptables en  embarqué, et après mesure, il trouve un petit écart en faveur du C++. Mais ce qui est important dans son discours est que le C++ ne dégrade ni les performances ni les tailles des exécutables en embarqué.

                                        -
                                        Edité par lmghs 28 septembre 2021 à 1:48:01

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                          28 septembre 2021 à 13:11:17

                                          Je veux bien que le C++ moderne permette de mettre un cadre pour que Jean-Michel puisse intervenir sur le projet sans passer 3 heures à lui expliquer le fonctionnement sur mesure qui s'éloigne des pratiques standards, mais comment faire quand le fonctionnement moderne empêche purement et simplement d'arriver à faire ce qu'on veut. Par exemple, imaginons qu'on ait envie d'avoir un backbuffer qu'on utilise si besoin. On va donc le déclarer, et si besoin, lancer la lourde phase d'initialisation :

                                          class Jeu {
                                            BackBuffer bb; // ne t'initialise pas stp !!
                                          
                                            Jeu() = default; // pas de bb
                                            Jeu(int width, int height) {
                                              // On veut un bb
                                              bb = BackBuffer(width, height);
                                            }
                                          };
                                          
                                          

                                          Vous allez me dire qu'il suffit de mettre un default constructor dans BackBuffer et je suis d'accord, mais le problème est que le destructeur de BB sera appelé dans tous les cas, même si on n'a jamais voulu l'initialiser ! Comment faire donc dans ce cas pour éviter que le destructeur soit appelé ? Alors on pourrait aussi faire un check dans le destructeur pour s'assurer que l'objet contient bien quelque chose à détruire (dans le cas où on l'a vraiment initialisé), mais ça fait que ce check sera quand même exécuté (aussi rapide soit-il), alors qu'il n'y avait aucune raison !

                                          Un autre problème serait si on a par exemple un Renderer. Si on met directement le code de l'initialisation dans le constructeur (ce qui parait logique à première vue), ça fait que ce code sera exécuté systématiquement dès qu'un renderer est ne serait-ce que déclaré (sans même appeler explicitement le constructeur). Mais imaginons que ce renderer se trouve dans une DLL qui est rechargée à chaud à volonté. On n'a certainement pas envie de réinitialiser le renderer à chaque rechargement à chaud. Du coup comment faire ? Moi je propose d'avoir une struct Renderer qui ne fait rien, et si on veut un renderer en tant que tel, on appelle une fonction genre `initRenderer`, ce qui fait qu'on peut déclarer un renderer sans qu'il ne se passe rien, et quand on veut un renderer, on appelle une fonction qui l'initialise. Mais du coup on en revient à la manière de faire du C ! Donc ce que je vois c'est que à la C on peut toujours s'en sortir alors que si on commence à utiliser des RAII et compagnie on est f**ed up, du coup comment faire dans ce cas ?

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            28 septembre 2021 à 13:55:35

                                            Si on tient absolument à enfoncer une vis avec un marteau, la seule solution est en effet de taper sur la vis avec.

                                            Ça n'en fait pas une bonne solution tout court.

                                            -
                                            Edité par michelbillaud 28 septembre 2021 à 13:58:10

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              28 septembre 2021 à 15:04:34

                                              Je ne vois rien dans le "C++ modern" qui oblige l'utilisation de la POO, qui interdit l'initialisation paresseuse, etc...

                                              Et votre "solution" pour la Dll est une caricature de "bonne idée" car vous ne semblez même pas savoir que l'ABI du C++ n'est pas (encore ?) standardisée.

                                              Critiquer, oui, mais faut savoir un peu de quoi on parle.

                                              Une API de Dll en C++, c'est vraiment pour faire du "jouet", c'est pédagogique, rien d'autre.

                                              Continuez de prendre le C++ pour un marteau, ce n'en fait pas un, et un programmeur un peu plus subtile qu'un "marteleur", normalement.

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                              Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
                                                28 septembre 2021 à 15:07:28

                                                JadeSalina a écrit:

                                                Un autre problème serait si on a par exemple un Renderer. Si on met directement le code de l'initialisation dans le constructeur (ce qui parait logique à première vue)

                                                Logique? pas trop d'accord, avoir une fonction dédiée à l'initialisation permet de:

                                                1) définir quand on veut lancer le comportement lourd(qui peut impliquer un chargement pour l'utilisateur) afin de grouper les chargements.

                                                2) mocker la function, afin de tester indépendement certaines parties de la classe(sa config par exemple) sans passer par le chargement.

                                                3) recharger/relancer le système au besoin.

                                                4) avoir une instance valide, même si le chargement a échoué pour supporter un null object pattern et garder un état prévisible de l'app.

                                                5) avoir une sémantique claire de ce qui se passe.

                                                6) fournir différentes possibles initialisations sans jouer avec les params ou constructeurs surchargés

                                                7) de lier des callback à l'initialisation pour notifier de son avancement.

                                                8) d'autres trucs...

                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  28 septembre 2021 à 15:11:53

                                                  Avec mon expérience de moyen-débutant, ton "backbuffer bb" je l'aurais déclaré en utilisant un smart pointer, comme c'est une ressource qu'on ne veut pas forcément initialiser (ce que tu fais par ailleurs en le déclarant de cette manière...).

                                                  Comme ca ton destructeur ne sera pas appelé puisque l'objet ne sera pas construit à tous les coups.

                                                  Et pour avoir un certain bagage quand même (et une certaine ancienneté sur ce forum), insinuer que des poids lourds comme gbdivers, lmghs ou autres devs avec pour la plupart 10 ans passés de dev pro derrière eux, c'est un peu du foutage de g***** :euh:

                                                  En te lisant on croirait vraiment entendre un fanatique (ô grand dieu Handemade Hero / casey / JeNeSaisQuoiDAutre)

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    28 septembre 2021 à 15:23:38

                                                    JadeSalina a écrit:

                                                    du coup comment faire dans ce cas ?

                                                    On ne reste pas bloqué dans ses idées juste pour essayer de montrer qu'on a raison, on apprend correctement le C++ et surtout, on arrête de s'inventer des problèmes pour rien.

                                                    Vu les différents commentaires et ce que j'ai vu et lu de tes sources, tu sembles (et les auteurs que tu cites) comprendre le C++ et la POO comme il y a 20 ans, tu fais des critiques qui datent d'il y a 20 ans, et tes solutions sont également vieilles de 20 ans. Tes messages montrent juste que tu ne sais pas du tout de quoi tu parles. C'est d'un ridicule consternant.

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      28 septembre 2021 à 15:41:14

                                                      P.X.L a écrit:

                                                      JadeSalina a écrit:

                                                      Un autre problème serait si on a par exemple un Renderer. Si on met directement le code de l'initialisation dans le constructeur (ce qui parait logique à première vue)

                                                      Logique? pas trop d'accord, avoir une fonction dédiée à l'initialisation permet de:

                                                      Oui je vois bien que les factory fonctions sont utiles, mais du coup ça ne suit pas la logique de "je déclare un objet = il est initialisé" (RAII), qui est la façon idiomatique de faire en C++. Ca veut dire qu'il faut parfois faire des entorses à la méthode C++ ?

                                                      P.X.L a écrit:

                                                      JadeSalina a écrit:

                                                      Un autre problème serait si on a par exemple un Renderer. Si on met directement le code de l'initialisation dans le constructeur (ce qui parait logique à première vue)

                                                      3) recharger/relancer le système au besoin.

                                                      Je croyais qu'il fallait faire 

                                                      obj = Obj{};

                                                      ce qui permet d'appeler le destructeur de obj courant tout en créant un nouveau qui sera correctement initialisé

                                                      gbdivers a écrit:

                                                      JadeSalina a écrit:

                                                      du coup comment faire dans ce cas ?

                                                      On ne reste pas bloqué dans ses idées juste pour essayer de montrer qu'on a raison, on apprend correctement le C++ et surtout, on arrête de s'inventer des problèmes pour rien.

                                                      Vu les différents commentaires et ce que j'ai vu et lu de tes sources, tu sembles (et les auteurs que tu cites) comprendre le C++ et la POO comme il y a 20 ans, tu fais des critiques qui datent d'il y a 20 ans, et tes solutions sont également vieilles de 20 ans. Tes messages montrent juste que tu ne sais pas du tout de quoi tu parles. C'est d'un ridicule consternant.


                                                      Je me demande justement quelle serait la façon moderne de faire en C++, parce que le problème c'est que je connais le C++ moderne et je vois pas comment faire autrement qu'en "reprenant les rennes" et en sortant légèrement des pratiques modernes, et btw c'est un vrai problème que j'ai, ce n'est pas un inventé de toute pièce. Et vous voulez dire que aujourd'hui il faut utiliser le plus de bibliothèques possibles et ne jamais savoir comment les choses fonctionnent réellement ? Car dans HH il fait peut être tout lui même sans tester ou autre mais ça permet de savoir comment les choses fonctionnent sans avoir des couches d'abstractions. Moi par exemple je comprenais pas comment fonctionnaient les streams, et bien il en a fait vers l'épisode 450, et du coup je comprends mieux, ce qui est intéressant non ?

                                                      nours59 a écrit:

                                                      Avec mon expérience de moyen-débutant, ton "backbuffer bb" je l'aurais déclaré en utilisant un smart pointer, comme c'est une ressource qu'on ne veut pas forcément initialiser (ce que tu fais par ailleurs en le déclarant de cette manière...).

                                                      Comme ca ton destructeur ne sera pas appelé puisque l'objet ne sera pas construit à tous les coups.


                                                      Le problème est qu'en faisant ça, le bb est stocké dans le tas, avec tout ce que ça implique, et si par exemple on voulait explicitement qu'il soit réellement contenu dans une classe sans être un pointeur ?

                                                      Et votre "solution" pour la Dll est une caricature de "bonne idée" car vous ne semblez même pas savoir que l'ABI du C++ n'est pas (encore ?) standardisée. Une API de Dll en C++, c'est vraiment pour faire du "jouet", c'est pédagogique, rien d'autre.

                                                      extern "C" ?

                                                      -
                                                      Edité par JadeSalina 28 septembre 2021 à 16:05:05

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        28 septembre 2021 à 15:45:57

                                                        mais si tu as besoin d'aller chercher des données sur ton objet c'est que tu en as eu besoin, donc tu as dû au moins l'initialiser? non?

                                                        Sinon c'est pour moi une erreur de conception (ou alors je n'ai pas tout compris...)

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          28 septembre 2021 à 15:58:50

                                                          EDIT

                                                          Oups j'ai flingué le message en voulant corriger un truc. Revoila le source avec Optional

                                                          #include <iostream>
                                                          #include <optional>
                                                          
                                                          using namespace std;
                                                          
                                                          class HeavyThing {
                                                          public:
                                                          	HeavyThing() {
                                                          		cout << "THE HEAVY THING is constructed" << endl;
                                                          	}
                                                          	void use() {
                                                          		cout << "THE HEAVY THING is used" << endl;
                                                          	}
                                                          };
                                                          
                                                          class Task {
                                                          	optional<HeavyThing> heavy;
                                                          
                                                          public:
                                                          	Task() {
                                                          		cout << "Task created but not fully unitialized" << endl;
                                                          	}
                                                          	void init() {
                                                          		cout << "Initializing..." << endl;
                                                          		heavy.emplace();
                                                          	}
                                                          
                                                          	void run() {
                                                          		cout << "running task" << endl;
                                                          		heavy->use();
                                                          	}
                                                          };
                                                          
                                                          int main() {
                                                          	Task t;
                                                          	cout << "task not initialized yet" << endl;
                                                          	
                                                          	t.init();
                                                          	t.run();
                                                          	t.run();
                                                          }
                                                          

                                                          et l'exécution

                                                          $ g++ -std=c++17 opt.cc 
                                                          $ ./a.out 
                                                          Task created but not fully unitialized
                                                          task not initialized yet
                                                          Initializing...
                                                          THE HEAVY THING is constructed
                                                          running task
                                                          THE HEAVY THING is used
                                                          running task
                                                          




                                                          > la doc disait

                                                          If an optional<T> contains a value, the value is guaranteed to be allocated as part of the optional object footprint, i.e. no dynamic memory allocation ever takes place. Thus, an optional object models an object, not a pointer, even though operator*() and operator->() are defined.

                                                          Au passage, si le truc à initialiser plus tard est vraiment un TRES GROS objet qui prend plein de place, c'est peut être pas exactement une idée géniale de poser comme prérequis qu'on ne veut pas qu'il soit alloué sur le tas.

                                                          Parce que bon, l'espace sur la pile est critique aussi, JDCJDR.

                                                          -
                                                          Edité par michelbillaud 28 septembre 2021 à 16:44:09

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            28 septembre 2021 à 16:03:30

                                                            JadeSalina a écrit:

                                                            P.X.L a écrit:

                                                            JadeSalina a écrit:

                                                            Un autre problème serait si on a par exemple un Renderer. Si on met directement le code de l'initialisation dans le constructeur (ce qui parait logique à première vue)

                                                            Logique? pas trop d'accord, avoir une fonction dédiée à l'initialisation permet de:

                                                            Oui je vois bien que les factory fonctions sont utiles, mais du coup ça ne suit pas la logique de "je déclare un objet = il est initialisé" (RAII), qui est la façon idiomatique de faire en C++. Ca veut dire qu'il faut parfois faire des entorses à la méthode C++ ?

                                                            Je suis dev java, pas C++, mais peu importe le langage, il y a toujours une manière préférée de faire les choses, un standard, un pattern, ce n'est pas pour autant que ça en devient l'unique vérité.

                                                            Le but d'un langage, c'est de construire des outils pour solutionner un problème, pas de s'enfermer dans une syntaxe, c'est un peu comme si, par principe tu ne parlais avec des gens qui pratiquent un dialecte, la version du français parfaitement conforme aux standards de l'Académie Française, qu'est ce qui est préférable: vaut il mieux s'adapter? ou encore se plaindre de leur mauvais français? se plaindre de l'Académie?

                                                            Tu peux continuer à te plaindre, moi je préfère être pragmatique et m'adapter, je trouve d'ailleurs que la pratique d'un langage a beaucoup plus de charme lorsque qu'elle est faîte de manière créative plutot que dogmatique, ça ouvre bien plus de possibilités.

                                                            le raii (ou son alter ego limité java, le try with resources) ont été conçus pour répondre à un besoin, dans certains cas, le besoin diffère, pas de secret, la solution devra différer aussi si on désire une solution et non un problème.

                                                            P.X.L a écrit:

                                                            JadeSalina a écrit:

                                                            Un autre problème serait si on a par exemple un Renderer. Si on met directement le code de l'initialisation dans le constructeur (ce qui parait logique à première vue)

                                                            3) recharger/relancer le système au besoin.

                                                            Je croyais qu'il fallait faire 

                                                            obj = Obj{};

                                                            ce qui permet d'appeler le destructeur de obj courant tout en créant un nouveau qui sera correctement initialisé

                                                            On a pas forcément besoin de tout reconstruire

                                                            PS: je hais la gestion des citations sur ce forum

                                                            -
                                                            Edité par P.X.L 28 septembre 2021 à 16:04:22

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              28 septembre 2021 à 17:15:18

                                                              >extern "C" ?

                                                              Entre autre, mais aussi cloisonnement mémoire, usage d'handle, de classe de wrapping header-only pour les maniacs de la POO, etc...

                                                              Vous faites du "C++ moderne" un "homme de paille" en n'en faisant qu'une caricature à la truelle.

                                                              Qu'il soit perfectible, on a droit des nouveaux standards tous les 2 à 3 ans donc oui, il est perfectible, mais totalement inutile, "faut pas pousser mémé dans les orties".

                                                              Tous les cas que vous nous donnez pour "discréditer" le C++ moderne se révèlent être une illustration de votre méconnaissance du C++ moderne (bien naturelle pour une personne peu expérimentée) ou d'une application "aveugle" de préceptes à l'emporte-pièce.

                                                              C'est à croire que la théorie qui sous-tend la Novlangue de "1984" serait une réalité.

                                                              Bin non, un langage, informatique ou pas, ne bride pas la pensée, quand il est bien maîtrisé et pas sclérosé par du "près à penser".

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

                                                              A quoi sert le C++ moderne ?

                                                              × 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