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 :

Déclaration anticipée ou destructeur par défaut?


Sujet :

C++

  1. #41
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Ehonn Voir le message
    On parle d'exception dans le constructeur avec de l'allocation dynamique et l'exemple que tu donnes est un code qui n'a ni queue ni tête et qui fait un throw 2; juste pour le plaisir.
    Certes ce n'est pas toujours évidant de donner du code logique et minimal lorsqu'on veut montrer un problème relativement complexe mais bon là c'est vraiment trop artificiel.
    Je ne vois pas le problème d'un exemple artificiel. Si c'est pinailler pour le plaisir de pinailler...

    Au dessus de ça, ton code est gênant car il empêche l'utilisateur d'attraper une autre exception que int.
    Et ? Cela dit explicitement que ton constructeur ne pourra lancer qu'un int, c'est un "contrat" que tu passes avec l'utilisateur de ta classe.
    Si une autre exception est lancée, ce sera un bug de la classe/bibliothèque.

    Ensuite, un bad_alloc ne se produit qu'en embarqué ou dans le cas d'une boucle infinie (ou d'une implémentation perso de new).
    Donc si on ne développe pas dans l'embarqué, je pense qu'on peut raisonnablement ignorer bad_alloc surtout si le fait que l'application plante n'est pas critique.
    Bon après il y a toujours des cas particuliers, mais c'est qu'un exemple, je n'ai pas la prétention d'écrire du code universel.

  2. #42
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    De plus, il avale l'exception, laissant derrière lui un objet que l'utilisateur croit construit, mais qui ne l'est pas vraiment.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  3. #43
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    De plus, il avale l'exception, laissant derrière lui un objet que l'utilisateur croit construit, mais qui ne l'est pas vraiment.


    Il "n'avale" pas l'exception, il rentre dans le catch pour détruire l'instance mais l'exception est toujours lancée.
    Je peux faire un test si vous souhaitez.

  4. #44
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Ah, c'est ces try/catch bizarres qui entourent tout le constructeur et ne suivent pas les règles habituelles, je n'avais pas vu...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #45
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Citation Envoyé par Neckara Voir le message
    Et ? Cela dit explicitement que ton constructeur ne pourra lancer qu'un int, c'est un "contrat" que tu passes avec l'utilisateur de ta classe.
    Si une autre exception est lancée, ce sera un bug de la classe/bibliothèque.
    Troll : donc tu postes volontairement du code buggé sur le forum ? (Je m'arrête ici pour cette partie)

    Citation Envoyé par Neckara Voir le message
    Ensuite, un bad_alloc ne se produit qu'en embarqué ou dans le cas d'une boucle infinie (ou d'une implémentation perso de new).
    Donc si on ne développe pas dans l'embarqué, je pense qu'on peut raisonnablement ignorer bad_alloc surtout si le fait que l'application plante n'est pas critique.
    Bon après il y a toujours des cas particuliers, mais c'est qu'un exemple, je n'ai pas la prétention d'écrire du code universel.
    Chez moi ce code envoie une exception et je suis sur Debian GNU/Linux Jessie avec GCC 4.9 sur un Intel Quad core :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
     
    #include <iostream>
     
    int main()
    {
    	long double * p = new long double[100000000000];
    	std::cout << p << std::endl;
     
    	delete p;
     
    	return 0;   
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    $ g++ -Wall -Wextra -Wconversion -Wsign-conversion -std=c++11 -pedantic -fopenmp main.cpp -o main && ./main
    terminate called after throwing an instance of 'std::bad_alloc'
      what():  std::bad_alloc
    Abandon
    Là c'est un exemple artificiel mais même sur une grosse machine avec 48 Go de RAM, certaines classes des NAS parallel Benchmark font des std::bad_alloc.
    Dans une application scientifique ou pour un serveur qui accepte des clients, ignorer les soucis d'allocation n'est pas une option.
    Même de façon générale, c'est jamais agréable d'avoir une application qui plante (surtout si cela peut être évité) (surtout si cela arrive au milieu ou à la fin de l'exécution).

  6. #46
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 145
    Points
    23 145
    Par défaut
    C'est vrai qu'on fait tous les jours des allocations de 93Go .
    Donc soit :
    • tu alloues volontairement trop pour faire planter ton new, mais je ne vois pas trop l'intérêt ;
    • tu as une boucle infinie qui te fait pleins de petites allocations ;
    • tu as un calcul erroné (= bug) char * toto = new char[ myStrlen("foo") ]; et dans ce cas là, il peut être plus intéressant que l'application plante plutôt de cacher l'erreur sous le tapis ;
    • tu laisse l'utilisateur choisir la taille à allouer sans aucune vérification.



    Et comme je l'ai dit :
    Bon après il y a toujours des cas particuliers.
    EDIT : C'est comme dire qu'un exemple où il y a une exception est "mauvais" car parfois, dans l'embarqué, les exceptions sont trop coûteuses/ne peuvent pas être utilisée.

  7. #47
    Membre chevronné Avatar de Ehonn
    Homme Profil pro
    Étudiant
    Inscrit en
    Février 2012
    Messages
    788
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2012
    Messages : 788
    Points : 2 160
    Points
    2 160
    Par défaut
    Les applications scientifiques, les serveurs, les programmes avec des données qui dépendent de l'utilisateur et/ou de l'architecture sont loin d'être des cas particuliers. De plus les programmes tournent rarement seuls sur une machine.

    Personnellement, je préfère qu'un navigateur Internet me dise qu'il ne peut pas ouvrir un nouvel onglet plutôt que de planter en me disant std::bad_alloc.
    L'erreur n'est pas forcément « cacher sous le tapis », elle est attrapée et traitée (et je pense aussi que dans la plupart des cas, on annulera la tâche qu'on a essayé de faire et affichera le problème à l'utilisateur en lui disant de tenter d'essayer avec plus de mémoire et de reporter le problème (avec éventuellement un joli formulaire pré-rempli)).

  8. #48
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    On va couper court au débat : les spécifications d'exception dynamique c'est déprécié (Norme 15.4 dernière note et annexe D).

    @Médinoc: C'est un GotW que tu cherches pour l'explication de la gestion manuel de plusieurs ressources : GotW 66 : Constructor failures et GotW 89 : Smart pointers.

  9. #49
    Expert éminent sénior

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 031
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 031
    Points : 11 379
    Points
    11 379
    Billets dans le blog
    10
    Par défaut
    Pour en revenir au point initial, j'utilise personnellement la déclaration anticipée.
    Pour tout dire, j'écris même généralement un fichier Prerequisites.h dans lequel je déclare mes classes.
    Il n'y a que quand j'utilise un membre non pointeur et non référence que j'inclue le header correspondant, sinon j'inclue mon Prerequisites.h

    * après de rapides tests, il est possible d'utiliser des pointeurs intelligents avec une déclaration anticipée, pourtant il me semblait que cela posait problème (?).
    Alors je ne sais pas si j'ai rêvé ou si le problème existait avec g++ < 4.9 (?).
    Par rapport à ça, si je ne me trompe pas, seul std::unique_ptr a besoin de la déclaration de la classe (destructeur surtout, je crois). std::shared_ptr n'en a pas besoin et std::weak_ptr encore moins.
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  10. #50
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Concernant la question initiale : une delete sur un type incomplet c'est tout sauf une bonne idée (destructeur non appelé) donc ton code avec déclaration anticipée n'est pas valide (et un unique_ptr ne change rien, on peut utiliser les pointeurs intelligents sur les types incomplets, mais ils doivent être complets au moment de la destruction pour que le code soit valide).

    Par contre si tu fais une séparation déclaration et définition en effectuant une déclaration anticipée dans la déclaration de la classe et une inclusion dans la définition alors ton code est valide.

    J'aurais aussi tendance à écrire ton premier exemple avec unique_ptr et make_unique pour une raison simple : tu as besoin de gérer une ressource et ces outils sont là pour ça, pourquoi je m'en priverais ? De plus ça me permet de me concentrer sur ce que doit réellement faire la classe (tout en forçant l'orthogonalité de l'implémentation). Dit autrement, oui ta classe respecte le RAII, mais pourquoi ne pas directement utiliser un outil qui va t'assurer systématiquement le RAII plutôt que de le faire manuellement (ce qui devient complexe dès que ta classe grandit un peu) ?

    Pour ta remarque concernant vector, personnellement j'aurais à l'implémenter, je le ferais surement en passant par un unique_ptr quelque part (à voir quand même si c'est faisable par rapport à ce qu'impose la norme au niveau de l'allocateur), sauf si je montre que ça diminue réellement les performances.

  11. #51
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 965
    Points
    32 965
    Billets dans le blog
    4
    Par défaut
    Un avantage au premier exemple : limiter les include dans les hpp
    Sur un gros projet, ça peut nettement diminuer le temps de compilation et c'est très appréciable !
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

Discussions similaires

  1. Réponses: 2
    Dernier message: 23/05/2007, 14h05
  2. [TListBox] Selection par défaut
    Par Nuts07 dans le forum Composants VCL
    Réponses: 8
    Dernier message: 12/05/2003, 10h00
  3. Couleur de sélection par défaut
    Par sicard_51 dans le forum AWT/Swing
    Réponses: 2
    Dernier message: 20/04/2003, 23h35
  4. [SWING][FONT] choisir la police par défaut
    Par narmataru dans le forum AWT/Swing
    Réponses: 4
    Dernier message: 21/02/2003, 10h35
  5. Retour au mode texte par défaut
    Par coca dans le forum x86 16-bits
    Réponses: 6
    Dernier message: 12/12/2002, 17h22

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