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 :

Constructeur statique (ou automatique) appelé plusieurs fois sur même objet


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Par défaut Constructeur statique (ou automatique) appelé plusieurs fois sur même objet
    Bonjour,

    J'aimerai avoir vos avis sur l'exemple suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    Classe C
    {
      int m_x;
      int m_y;
      int m_z;
     
      public :
        C(int x, int y, int z)
        {
           m_x = x;
           m_y = y;
           m_z = z;
        }
    }
     
    main.cpp :
    ...
    C c = C(3, 6, 8);
    ...
     
    while(...)
    {
      val_x = ...;
      val_y = ...;
      val_z = ...;
     
      c = C(val_x, val_y, val_z);
     ...
    }
     
    ...
    Outre le fait que le constructeur soit utilisé comme un gros setter(), n'y a-t-il pas de risque ou de problème à appeler plusieurs fois le constructeur sur le même objet, qui plus est dans un while ?

    Merci de votre aide.

  2. #2
    Membre Expert Avatar de jabbounet
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juin 2009
    Messages
    1 909
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Juin 2009
    Messages : 1 909
    Par défaut
    Dans un code du genre (attention je ne l'ai pas compilé):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    int x = 0;
    int y = 1000;
    int z = 50;
     
    while (x < y)
    {
         C locale(x,y,z);
         C* pasLocale = new C(x*2,y*2,z*2);
     
         x +=z;
         y -= z;
    }
    Ajoute une trace (std::cout) dans les constructeurs/destructeurs de la classe C et tu verra ce qu'il se passe.
    Autre solution utiliser le débugger.

    La manipulation est simple a faire et l'expérimentation aide beaucoup pour apprendre et retenir.

    Une notion fondamentale a regarder en C/C++ sont la notion de pile et de tas ainsi que la durée de vie/portée des variables/objets

  3. #3
    Membre éclairé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Par défaut
    Citation Envoyé par jabbounet Voir le message

    Ajoute une trace (std::cout) dans les constructeurs/destructeurs de la classe C et tu verra ce qu'il se passe.
    Autre solution utiliser le débugger.
    Je l'ai fait, et à chaque tour de boucle, le constructeur est appelé deux fois (comme prévu).

    Citation Envoyé par jabbounet Voir le message
    La manipulation est simple a faire et l'expérimentation aide beaucoup pour apprendre et retenir.
    Je vois pas bien où tu veux en venir, désolé.

  4. #4
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Bonjour,

    de quel risque parles-tu ?
    Il n'y a aucun risque, oui les constructeurs/destructeurs sont souvent appelés, mais est-ce dérangeant ? Pourquoi ?

    D'ailleurs, ce n'est pas le constructeur qui sera appelé dans la boucle, mais plus surement l'opérateur d'affectation.
    Tout comme la première affectation à la déclaration peut utiliser le constructeur par copie.
    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.

  5. #5
    Membre éclairé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Bonjour,

    de quel risque parles-tu ?
    Il n'y a aucun risque, oui les constructeurs/destructeurs sont souvent appelés, mais est-ce dérangeant ? Pourquoi ?

    D'ailleurs, ce n'est pas le constructeur qui sera appelé dans la boucle, mais plus surement l'opérateur d'affectation.
    Tout comme la première affectation à la déclaration peut utiliser le constructeur par copie.
    Je parle de risque de fuite de mémoire par exemple, et même si ce n'est pas le cas peut-être, je trouve que ce n'est pas une bonne pratique d'utiliser le constructeur comme setter() et l'appeler en boucle de la sorte.

    Suis-je le seul à trouver que ce n'est pas une bonne pratique?

  6. #6
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    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 026
    Par défaut
    Le constructeur est fait pour initialiser les attributs.
    Soit il les initialise lui-même, soit il appelle des setters donc je ne vois pas où est le problème.

    Dans la boucle :
    C locale(x,y,z);Créera un objet différent à chaque tour et sera détruit en fin de tour de boucle.
    Pour C* pasLocale = new C(x*2,y*2,z*2);On aura en effet une fuite de mémoire car il n'y a pas de delete, mais ça n'a rien à voir avec le constructeur.

    Il peut en effet y avoir une fuite de mémoire dans un constructeur mais il sera dû à un delete manquant dans le destructeur.

    Le constructeur n'est appelé qu'une seule fois lors de la création de l'objet.

    C'est ce que jabbounet voulait te montrer avec son exemple.

  7. #7
    Rédacteur/Modérateur


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

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Citation Envoyé par LinuxUser Voir le message
    Je parle de risque de fuite de mémoire par exemple, et même si ce n'est pas le cas peut-être, je trouve que ce n'est pas une bonne pratique d'utiliser le constructeur comme setter() et l'appeler en boucle de la sorte.

    Suis-je le seul à trouver que ce n'est pas une bonne pratique?
    Une fuite mémoire n'est pas lié à un constructeur mais imputable au développeur qui a fait de la merde. Que ce soit un constructeur pourri, ou toute autre méthode qui ne prend pas en compte tous les paramètres (allouer un membre ? cas où il est déjà alloué ? le supprimer pour le réallouer ? ... ?).
    Les bonnes pratiques, comme leur nom l'indique, ce sont des pratiques. Et rien ni personne ne peut empêcher quelqu'un de faire de la merde et d'aller à leur encontre.

    De plus dans ce cas, très/trop simple, il n'y a aucune mémoire gérée dynamiquement, et ce sont plus surement les opérateurs d'affectation et constructeur de copie qui sont utilisés.
    Le seul constructeur vraiment utilisé est pour créer l'objet temporaire C(val_x, val_y, val_z) dans la boucle.
    c est créé en amont de la boucle.

    Le constructeur devrait utiliser les liste d'initialisation.
    Il faudrait ajouter le constructeur par copie et l'opérateur d'affectation. Ceux par défaut font l'affaire mais ça permet de savoir par où l'on passe.
    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.

  8. #8
    Membre émérite

    Profil pro
    Inscrit en
    Décembre 2008
    Messages
    533
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2008
    Messages : 533
    Par défaut
    Ajoute un setter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    while(...)
    {
      val_x = ...;
      val_y = ...;
      val_z = ...;
     
      c.setCoordinates(val_x, val_y, val_z);
     ...
    }
    Ou met tes attributs en public (je risque de faire jaser, là) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    while(...)
    {
      c.x = ...;
      c.y = ...;
      c.z = ...;
    }
    Mais c'est vrai que créer un objet temporaire pour l'affecter à c n'est pas une bonne méthode. Sans parler des performances, si ton code évolue et que tu décides d'ajouter un attribut w à ta classe C, tu risques d'écraser w alors que le code original n'est censé modifier que x, y et z. Sans parler du chaos que w engendrerait dans le cas où ce serait un pointeur et où C::operator=(const C&) ne serait pas méticuleusement redéfini.

  9. #9
    Membre éclairé Avatar de LinuxUser
    Inscrit en
    Avril 2007
    Messages
    857
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 857
    Par défaut
    Citation Envoyé par cob59 Voir le message
    Ajoute un setter :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    while(...)
    {
      val_x = ...;
      val_y = ...;
      val_z = ...;
     
      c.setCoordinates(val_x, val_y, val_z);
     ...
    }
    Oui, c'est ce à quoi j'avais pensé.

    Citation Envoyé par cob59 Voir le message
    Ajoute un setter :
    Ou met tes attributs en public (je risque de faire jaser, là) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    while(...)
    {
      c.x = ...;
      c.y = ...;
      c.z = ...;
    }
    Nan là quand même pas.

    Citation Envoyé par cob59 Voir le message
    Ajoute un setter :
    Mais c'est vrai que créer un objet temporaire pour l'affecter à c n'est pas une bonne méthode. Sans parler des performances, si ton code évolue et que tu décides d'ajouter un attribut w à ta classe C, tu risques d'écraser w alors que le code original n'est censé modifier que x, y et z. Sans parler du chaos que w engendrerait dans le cas où ce serait un pointeur et où C::operator=(const C&) ne serait pas méticuleusement redéfini.
    Surtout que je récupère et découvre un code existant et justement j'essaye de faire les choses proprement pour le faire évoluer et ensuite le maintenir.

    En tout cas merci beaucoup à tous.

  10. #10
    screetch
    Invité(e)
    Par défaut
    aucun d'entre vous n'a lu la question correctement et n'a repondu correctement... (sauf Bousk)
    LinuxUser, n'ajoute pas de setter, le code que tu as fait est parfaitement valide.

    a chaque tour de boucle, le compilateur C++ va etendre le code que tu as montre:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    c = C(val_x, val_y, val_z);
    pour le "remplacer" par:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    C temp = C(val_x, val_y, val_z);
    c.operator=(temp);
    temp.~C();
    c'est a dire qu'il ne va pas ecraser la variable c par une nouvelle valeur comme ca, il va construire un temporaire puis utiliser un operateur C++ special que le compilateur peut generer automatiquement (mais parfois, pas parfaitement), et qui consiste a remplacer (proprement) les valeurs contenues dans c par les valeurs contenues dans temp, puis va detruire temp qui n'est plus utile.

    regarde dans la FAQ les constructeurs de copie, les operateurs d'affectation et les destructeurs; ces methodes sont speciales et sont mises en jeu dans le code exemple que tu montres.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 5
    Dernier message: 01/03/2015, 19h02
  2. Réponses: 0
    Dernier message: 18/09/2012, 11h56
  3. [Online] Appeler plusieurs fois la même fonction JS dans un form
    Par reitsab dans le forum Microsoft Dynamics CRM
    Réponses: 3
    Dernier message: 23/08/2011, 14h59
  4. Plusieurs fois le même objet dans un Canvas
    Par Invité dans le forum Windows Presentation Foundation
    Réponses: 3
    Dernier message: 27/06/2011, 16h46
  5. Réponses: 2
    Dernier message: 16/03/2009, 11h07

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