IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

eviter les pointeurs NULL


Sujet :

C++

  1. #1
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut eviter les pointeurs NULL
    Ce thread est un fork de cette discutions http://www.developpez.net/forums/sho...d.php?t=592996.


    Je code avec des restrictions très fortes, via des invariants garantis de préférence par le typage, limitant ainsi fortement la nécessité de tout tester.

  2. #2
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Je code avec des restrictions très fortes, via des invariants garantis de préférence par le typage, limitant ainsi fortement la nécessité de tout tester.
    Cela semble intéressant mais j'ai quelques difficultés à me représenter cela.
    Vous pourriez donner un exemple simple?
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Je n'utilise que des objets qui ne peuvent jamais être vide ou dans un état invalide et ceci avec une sémantique valeur.

  4. #4
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Je n'utilise que des objets qui ne peuvent jamais être vide ou dans un état invalide et ceci avec une sémantique valeur.
    Salut, tu aurais un exemples ou un lien de ce que tu parle???
    J'ai dû mal à comprendre...

  5. #5
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Je poursuis la remarque de loufoque:
    Citation Envoyé par loufoque Voir le message
    Je n'utilise que des objets qui ne peuvent jamais être vide ou dans un état invalide et ceci avec une sémantique valeur.
    Ce qui, en C++, signifie:
    * code résistant aux exceptions
    * RAII
    * type safety (ce qui permet une récupération d'une bonne partie des erreurs logique au moment de la compilation)
    * utilisation de la librairie standard

    Et autres techniques dont le but est de maximiser la validité du code. Le Saint Graal étant d'arriver à un code qui ne peut compiler que si il est correct (ce qui n'est pas prêt d'être le cas, mais en s'arrangeant bien, on peut déja obtenir des choses sympas en C++).
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Je poursuis la remarque de loufoque:

    Ce qui, en C++, signifie:
    * code résistant aux exceptions
    * RAII
    * type safety (ce qui permet une récupération d'une bonne partie des erreurs logique au moment de la compilation)
    * utilisation de la librairie standard

    Et autres techniques dont le but est de maximiser la validité du code. Le Saint Graal étant d'arriver à un code qui ne peut compiler que si il est correct (ce qui n'est pas prêt d'être le cas, mais en s'arrangeant bien, on peut déja obtenir des choses sympas en C++).
    Ce sont de bons principes de programmation: ils permettent de prévenir des aberrations dans les cas "limite" souvent difficiles à provoquer via des tests.

    Je ne pense pas qu'on puisse s'assurer que ces principes aient été respectés sans faire une revue du code.
    Et malheureusement coder proprement ne signifie pas toujours que çà fera "papa, maman" comme on l'attend

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par wiztricks Voir le message
    Ce sont de bons principes de programmation: ils permettent de prévenir des aberrations dans les cas "limite" souvent difficiles à provoquer via des tests.

    Je ne pense pas qu'on puisse s'assurer que ces principes aient été respectés sans faire une revue du code.
    Et malheureusement coder proprement ne signifie pas toujours que çà fera "papa, maman" comme on l'attend

    - W
    Non, franchement, respecter ces principes est très simple en C++, et ça se contamine très facilement à tout code qui vient se baser sur ça.

    Une classe dont tous les membres respectent le RAII respecte RAII, résiste aux exceptions.
    Et pour que tous ses membres respectent le RAII, s'aider de la librairie standard si besoin.

    ----

    Bon et sinon, j'suis déçu, personne n'essaie un minimum de garantir les invariants de la classe, en spécifiant à la main et en faisant quelles implications logiques ?

    Pour des objets dont l'implémentation est compliquée bien, pas pour un p'tit Timer à la con.

  8. #8
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Un pointeur, par exemple, ça peut être nul.
    Un pointeur de fonciton, ça peut être nul.
    Un Boost.Any, ça peut être nul.
    Un Boost.Function, ça peut être nul.

    Un objet dans un état nul invoque soit un comportement indéfini, soit une erreur, soit une exception.
    Des choses que je tiens à éviter entièrement par conception.

  9. #9
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    En fait je fais de même, je les evite.

    Sauf quand j'en ai besoin
    Quand la logique du programme implique une absence d'objet référé, c'est naturel d'utiliser un pointeur. Comme c'est dans la logique du programme, ça doit être géré. Et par là même, l'etat nul n'est jamais une erreur, si il est permis.

    Enfin dans l'idéal du moins.

  10. #10
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Dans le cas d'un objet optionnel, j'utilise un wrapper de type boost::optional<T> ou de type boost::variant<T, null_type>.

    Tout comme Some of 'a | None en ML ou le Maybe monad en Haskell.

    C'est tout de même souvent une erreur de conception que de devoir travailler avec des objets qui peuvent être nuls.

  11. #11
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Dans le cas d'un objet optionnel, j'utilise un wrapper de type boost::optional<T> ou de type boost::variant<T, null_type>.

    Tout comme Some of 'a | None en ML ou le Maybe monad en Haskell.

    C'est tout de même souvent une erreur de conception que de devoir travailler avec des objets qui peuvent être nuls.
    boost::optional<T>, j'aime pas trop, la valeur est ajoutée est pas énorme, dans le sens où le typage ne te force pas à vérifier si l'objet est nul ou non.

    Alors qu'à l'inverse boost::variant<T, null_type> ou le type Option de ML t'oblige à vérifier si l'objet est valide.

  12. #12
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    C'est tout de même souvent une erreur de conception que de devoir travailler avec des objets qui peuvent être nuls.
    Je ne vois pas en quoi?

    Le cas le plus courant sur le quel je tombe est simplement quand on a besoin de savoir quel objet on a a un moment, ou si on a pas d'objet.
    Par exemple une icone selectionnée ou aucune selectionnées, sont des etats valides dans beaucoup d'application (je pense principalement aux jeux vidéos là ou c'est très courant).
    De même dans les bases de données il est souvent utile d'indiquer que l'information est manquante par une valeur nulle (qui est différente d'un texte vide par exemple).

    A mon humble avis, remplacer systématiquement ce genre de logique par un objet est souvent overkill comme on dit, même si il ya des cas où c'est pertinent, ça ne semble pas l'etre pour tous les cas. D'ailleurs, ça n'aide pas forcément à la compréhension en travail d'équipe (quand toute l'équipe ne connais pas boost et n'a pas le temps de s'y mettre par exemple). Autant se servir des mécanismes de base du language.

  13. #13
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Le cas des champs nuls dans une base de données est un cas courant, oui.
    Après l'histoire des icônes j'ai pas compris. Un objet icône, une fonction is_checked et voilà...

  14. #14
    Membre Expert
    Avatar de Klaim
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Août 2004
    Messages
    1 717
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 717
    Par défaut
    Ah ben non is_checked suppose que tu vas parcourir un certain nombre d'icones pour voir laquelle est checkée/selectionnée. Je parlais d'un cas ou tu ne peux en avoir qu'une seule a la fois ou pas du tout.

    C'est correcte logiquement, mais pas du poitn de vu des perfs! (surtout
    De plus, tu as toujours le risque d'arriver a un état ou plusieurs icones sont selectionnées en même temps, or si ce n'est pas le comportement voulu (une seule maximum) c'est potentiellement un probleme.

    En fait mon exemple n'est pas clair.
    Imaginons que je fasse un petit jeu où on a une représentation de la main droite du héros. Cette main ne peut tenir qu'un seul item a la fois pour l'utiliser, ou pas d'item du tout. Chaque item est différent et unique et possède un pouvoir activé dés que le joueur le met dans la main du heros (une methode appliquant le pouvoir, appelée régulièrement).
    Tu as globalement deux manières de faire la partie qui permet de savoir quel objet on a dans la main (pour pouvoir appeler sa methode de pouvoir) ou qu'il n'y a pas d'objet dans la main :
    a) utiliser un identifiant (par exemple un index) et déclarer une valeur de cet identifiant qui corresponds à "pas d'objet".
    b) utiliser un pointeur vers l'objet en question, si il est a null alors il n'y a pas d'objet dans la main.

    En fait, c'est la même solution, sauf que a) nécessite de coder quelque chose qui est déjà là au final dans le language. De plus a) t'oblige a connaitre dans le code appelant la façon dont sont organisés les objets item. Même si le code est minime, c'est le même principe.
    Autant utiliser b) dans ce cas là par exemple.

  15. #15
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Pareil, utiliser un type qui rend explicitement optionnel le truc est bien plus sûr que des pointeurs.

  16. #16
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Je sais que c'est un peu hors sujet, mais je n'ai pas encore trouvé d'explication suffisament convaincante de cette affaire liée aux pointeurs NULL (comme quoi, avoir à en gérer serait un code smell...). Est-ce que quelqu'un maitrise bien le sujet ?
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  17. #17
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Pareil, utiliser un type qui rend explicitement optionnel le truc est bien plus sûr que des pointeurs.
    Si je comprend bien ce que tu dit, tu as toujours un objet qui correspond au NULL
    En gros un objet non initialisé que tu peut tester.
    Alors quel différence avec le teste d'un pointeur à 0 ؟

  18. #18
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par Mongaulois Voir le message
    Si je comprend bien ce que tu dit, tu as toujours un objet qui correspond au NULL
    En gros un objet non initialisé que tu peut tester.
    Alors quel différence avec le teste d'un pointeur à 0 ؟
    Cf mon message plus haut... http://www.developpez.net/forums/sho...3&postcount=11

    Boost.Variant t'oblige à distinguer à la compilation les deux cas, null ou pas, si tu l'utilises avec le visiteur qui va bien.

    > http://www.boost.org/doc/libs/1_35_0...l/variant.html

    Contourner le système de type ne compte pas évidemment... Dans ce cas là, rien n'est plus sûr du tout en C++. Utiliser la fonction membre get<>() contourne le typage...

    -----

    Bien sûr, je considère que Boost.Variant reste du hack, pour construire du pattern-matching à la sauce ML, et ça reste assez lourd pour des utilisations simples.

    Par contre, pour des structures arborescentes, c'est pas mal. Je l'ai utilisé pour faire un Abstract Syntax Tree une fois, on se croirait en OCaml.

  19. #19
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Bien sûr, je considère que Boost.Variant reste du hack
    Il faudra m'expliquer en quoi...
    C'est simplement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template<typename F>
    typenane F::result_type visit(const F& f)
    {
         switch(type)
         {
             case 0:
                  return f(*static_cast<Type0*>(value));
             case 1:
                  return f(*static_cast<Type1*>(value));
             ...
         }
    }
    Un objet dont le type est obfusqué, un entier qui identifie de quel type il s'agit, et un switch pour reconvertir l'objet obfusqué vers l'objet typé.
    Rien de magique.

  20. #20
    Membre émérite Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Par défaut
    Citation Envoyé par loufoque Voir le message
    Il faudra m'expliquer en quoi...
    C'est simplement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    template<typename F>
    typenane F::result_type visit(const F& f)
    {
         switch(type)
         {
             case 0:
                  return f(*static_cast<Type0*>(value));
             case 1:
                  return f(*static_cast<Type1*>(value));
             ...
         }
    }
    Un objet dont le type est obfusqué, un entier qui identifie de quel type il s'agit, et un switch pour reconvertir l'objet obfusqué vers l'objet typé.
    Rien de magique.
    Je sais mais je disais pas un hack au sens là.

    Mais plus le fait de devoir appliquer un visiteur, devoir écrire une classe et la faire hériter de boost::static_visitor<>, et tout le tralala qui va avec quoi.

    Plein de petites choses cumulées qui te donnent l'impression que tu n'es pas en train d'écrire quelque chose d'aussi direct qu'une fonction.

    ---

    Et alors quand tu veux écrire un Variant récursif, ça devient pire ! Pour écrire le type, tu te farcis un boost::recursive_wrapper en plus.

    Mais bon c'est pourtant une fonctionnalité qui vaut largement le coup!

Discussions similaires

  1. Mesure qui n'est pas lié à toutes les dimension => eviter les NULL
    Par khadhraoui1 dans le forum Décisions SGBD
    Réponses: 1
    Dernier message: 14/08/2014, 12h04
  2. Tester les Pointeurs Null
    Par hibou107 dans le forum Débuter
    Réponses: 13
    Dernier message: 27/05/2011, 14h11
  3. Réponses: 11
    Dernier message: 03/11/2007, 18h33
  4. Réponses: 4
    Dernier message: 13/08/2004, 18h39
  5. Pb de débutant sur les pointeurs!!!
    Par benji17c dans le forum C
    Réponses: 6
    Dernier message: 30/09/2003, 17h50

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo