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�butant] Constructeur ~Destructeur


Sujet :

C++

  1. #1
    Membre �clair� Avatar de grabriel
    Inscrit en
    Septembre 2006
    Messages
    946
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 946
    Par d�faut [D�butant] Constructeur ~Destructeur
    Bonjour,

    Concernant les constructeurs et les destructeurs j'ai lu sur un forum (peut �tre ici) que le fait d'utiliser new peux entrainer des fuites m�moires!!

    Ma question est quelle est la meilleur fa�on de construire et d�truire un objet?

    J'ai un peu de mal avec ce concept? le jour o� il y aura un garbage collector....


    Est ce que ceci est bon?
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    maClasse::maClasse(int unEntier, char* unPointeurChar)
    {
        unEntier = 3;
        unPointeurChar = "aa";
    }
     
    maClasse::~maClasse()
    {
        delete[] entier, unPointeurChar;
    }
    Avec un header qui d�clare �a :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    class maClasse
    {
      public :
        maClasse();
        ~maClasse();
     
      private :
        int unEntier;
        char *unPointeurChar;
    }
    Merci!

  2. #2
    Membre �prouv�
    Inscrit en
    Avril 2008
    Messages
    155
    D�tails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 155
    Par d�faut
    ben oui:
    si tu as

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class maClasse
    {
      public :
        maClasse();
        ~maClasse();
     
      private :    
        char *unPointeurChar;
    }
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    maClasse::maClasse(int unEntier, char* unPointeurChar)
    {
        unEntier = 3;
        unPointeurChar = "aa";
    }
     
    maClasse::~maClasse()
    {
     
    }
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
     
    for(;;)
    {
     maClase();
    }
    a chaque passage de boucle il y a 2 octets qui sont perdus.

    En r�gle g�n�rale, �vite d'utiliser les new/delete...
    Ou alors assure toi bien de faire un delete sur le pointeur attribut.

  3. #3
    Membre �prouv�
    Inscrit en
    Avril 2008
    Messages
    155
    D�tails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 155
    Par d�faut
    oups je me suis plant� de constructeur mais tu as compris

  4. #4
    Membre �clair�
    Inscrit en
    Mai 2005
    Messages
    73
    D�tails du profil
    Informations forums :
    Inscription : Mai 2005
    Messages : 73
    Par d�faut
    Tout d'abord, le code que tu proposes ne contient aucun new, donc aucune allocation de m�moire : inutile donc de la lib�rer.

    Cependant, si dans ton constructeur tu allouais de la m�moire, par exemple pour ton char * (soit dit en passant, affecter "aa" � un pointeur ne signifie rien : un pointeur est une adresse), alors il faudrait penser � lib�rer celle-ci dans ton destructeur :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    MaClasse:MaClasse()
    {
        unPointeurChar = new char;
    }
     
    MaClasse:~MaClasse()
    {
        delete unPointeurChar;
    }
    Quant � l'autre syntaxe que tu utilises, elle sert � lib�rer la m�moire occup�e par des tableaux. D'apr�s ce que j'ai compris, ton char * est en fait une cha�ne de caract�res. Dans ce cas, tu dois allouer de la m�moire pour plusieurs char, de la fa�on suivante :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    MaClasse:MaClasse()
    {
        unPointeurChar = new char[10];
        unPointeurChar[0] = 'a';
        unPointeurChar[0] = 'a'; //La chaîne contient maintenant "aa", ainsi que des données
                                 //indéfinies dans les 8 caractères restants
    }
    Encore une fois, comme tu as allou� de la m�moire, tu dois la lib�rer. La syntaxe pour lib�rer la m�moire occup�e par un tableau est la suivante :

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    MaClasse:~MaClasse()
    {
        delete[] unPointeurChar;
    }
    Cependant, il me semble qu'il faudrait d'abord que tu apprennes la s�mantique des pointeurs, ce qu'ils repr�sentent, avant de t'occuper d'allocation et de d�sallocation.

  5. #5
    Membre �clair� Avatar de grabriel
    Inscrit en
    Septembre 2006
    Messages
    946
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 946
    Par d�faut
    Oui j'ai oubli� d'utiliser des new, en faite c'�tait plus pour le principe...

    Je d�bute et donc ma syntaxe est encore imparfaite, mais si je suis amen� � utiliser des new � tout va (je faisait du java avant) je pr�f�re savoir comment m'en d�patouiller. J'ai pas envie de prendre de mauvaise habitude.


    En r�gle g�n�rale, �vite d'utiliser les new/delete...
    Faut faire comment pour cr�er de nouvelles classes??


    Merci pour vos r�ponses.

  6. #6
    Membre �prouv�
    Inscrit en
    Avril 2008
    Messages
    155
    D�tails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 155
    Par d�faut
    ben quand tu fais appel � un constructeur de la classe, un objet est cr��!
    pas besoin de faire des new � droite et � gauche...

    la dur�e de vie d'un objet n'exc�de pas le fichier ou les parenth�se

    c'est bon � rappeler:

    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    void main()
    {
      {
      maclasse objet;
      //ici au debugger tu pourras voir l'objet
      }
    //ici il n'existe plus ^^
    }

  7. #7
    Membre �clair� Avatar de grabriel
    Inscrit en
    Septembre 2006
    Messages
    946
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 946
    Par d�faut
    Ok!

    Ca d� m'�chapp�.

  8. #8
    Expert �minent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    D�tails du profil
    Informations personnelles :
    Sexe : Homme
    �ge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activit� : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par d�faut
    Salut,

    Oui, mais non...

    Oui car, de fait, si tu alloue dynamiquement de la m�moire pour un pointeur et que tu ne lib�re pas la m�moire, tu cours le risque d'une fuite m�moire, chaque fois que tu sors d'une port�e dans laquelle tu d�clare un pointeur.

    En effet, le langage estime que si "tu es suffisemment fou" pour vouloir g�rer toi m�me la m�moire allou�e � des objets, c'est que tu es "suffisemment comp�tant" pour savoir quand cette m�moire peut �tre lib�r�e, et donc te charger de le faire au moment le plus opportun

    Mais non, le code que tu pr�sente est tr�s loin d'�tre correct.

    En effet, delete (ou delete[]) ne peut �tre invoqu� que sur un pointeur allou� dynamiquement avec new (ou new[]).

    Il y a donc d�j� un probl�me avec la tentative d'invoquer delete sur ton entier (car ce n'est pas un pointeur)... et m�me si "la (mal)chance" est avec toi sur le coup pr�sent, du fait des particularit�s de l'usage de la virgule

    En outre, sur basse du code que tu fournis pour le constructeur, unPointeurDeChar ne pointe pas sur une adresse allou�e dynamiquement mais... sur l'adresse d'un tableau constant cr�� de mani�re strictement statique

    Je parle bien sur de ce code ci:
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    maClasse::maClasse(int unEntier, char* unPointeurChar)
    {
        unEntier = 3;
        unPointeurChar = "aa";
    }
    En effet, �tant donn� que tu passe des valeurs en arguments au constructeur, l'id�al est quand m�me de les utiliser pour initialiser les diff�rents membres, de pr�f�rence sous la forme d'une liste d'initialisation.
    Le code prendrait alors la forme de
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    maClasse::maClasse(int unEntier, char* unPointeurChar): unEntier(unEntier), unPointeurChar(unPointeurChar)
    {
    }
    Pour rappel, le but d'un constructeur est d'initialiser les membres de ta classe afin de fournir un objet directement utilisable.

    Si donc tu fournis des arguments au constructeur, tu t'attend � ce que les valeurs des diff�rents membres... correspondent � celle que tu a fournies en argument

    ainsi, tu ne comprendrait pas les valeurs des membres de obj cr�� � l'aide du code
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
     
    char tab[5]="toto\0";
    MaClass obj(5,tab);
    puissent �tre... 3 et "aa" (re )

    Ensuite, il faut quand quand meme se rappeler que le fait de lib�rer la m�moire qui �tait allou�e dynamiquement va automatiquement invalider tous les pointeurs qui pointent vers cette zone m�moire, ce qui risque de provoquer une erreur de segmentation lors de toute tentative d'acces � l'�l�ment point� par un pointeur se trouvant dans le cas.

    ainsi, le code ci-dessous pr�sente les deux cas "peau de banane":
    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
    int main()
    {
        char* tab;
        char nondyn[5]="toto\0";
        /*...*/
        tab=new char[7];
        /*...
         * ce qui suit peut etre un test ou une boucle, et le problème est encore 
         * plus grave si c'est une boucle
         */
        {
            MaClass obj(7,tab);//obj est créé ici
            /*...*/
        }/* et détruit ici (avec appel du destructeur, et 
           * donc il y a invocation de delete) (à chaque passage s'il s'agit dune
           * boucle avec des problème dés le deuxième passage par ici
           */
        /*
         * tab pointe ici vers une adresse devenue tout à fait invalide, et toute 
         * tentative d'utilisation de tab se soldera par une cata
         */
        /*...*/
        char nondyn[5]="toto\0";
        {
            MaClasse obj(5,nondyn);//obj est créé ici
        }/*et détruit ici, avec invocation de delete... que l'on tente d'appliquer
          * à une adresse mémoire qui n'a pas été allouée dynamiquement
          */
        return 0;
    }
    Evidemment, il existe de nombreuses possibilit�s de contourner tous ces probl�mes... Mais elles d�pendent �norm�ment de l'usage auquel tu destine ta classe

    Tout cela pour te faire comprendre que, Oui, le principal risque de l'allocation dynamique est la fuite m�moire mais, surtout, qu'une mauvaise gestion de la m�moire dynamique (induite entre autre par une mauvaise maitrise de la mani�re dont est utilis� l'objet) aura des cons�quences encore bien plus d�sastreuses.

    C'est la raison pour laquelle:
    1. on insiste �norm�ment sur les concepts de d�l�gation des responsabilit�s (clairement identifier qui est responsable de l'allocation dynamique et qui est responsable de la lib�ration de la m�moire, dans le cas)
    2. on pr�f�re laisser autant que possible la gestion de la m�moire � des classes dont on sait qu'elle la g�re correctement (entre autres toutes les classes fournies par la S(T)L)
    3. on choisi de travailler avec des pointeurs quand il n'y a pas d'autres choix (par exemple, pour certaines mises en oeuvre du polymorphisme, ou si un objet est sens� se contenir lui m�me)
    A m�diter: La solution la plus simple est toujours la moins compliqu�e
    Ce qui se con�oit bien s'�nonce clairement, et les mots pour le dire vous viennent ais�ment. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 f�vrier 2014
    mon tout nouveau blog

  9. #9
    Membre �clair� Avatar de grabriel
    Inscrit en
    Septembre 2006
    Messages
    946
    D�tails du profil
    Informations forums :
    Inscription : Septembre 2006
    Messages : 946
    Par d�faut
    Merci pour ces explications c'est plus claire mais �a reste encore floue...

    J'ai encore du boulot...

  10. #10
    Membre �clair� Avatar de befalimpertinent
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    561
    D�tails du profil
    Informations personnelles :
    �ge : 41
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Avril 2007
    Messages : 561
    Par d�faut
    Comprendre les diff�rences entres les allocations admises par le c++ (dois je allouer sur la pile (statique) ou sur le tas (dynamique --> new, delete) ? ) est quel que chose de primordiale ?
    Un bon conseil : assures toi de bien avoir compris ce point avant de te lancer dans un projet important.

    Quelques ref:
    diff�rence pile, tas
    gestion dynamique de la m�moire

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. Constructeur & Destructeur en UML
    Par fredhali2000 dans le forum UML
    R�ponses: 5
    Dernier message: 31/03/2006, 19h31
  2. [D�butant] Constructeur d'une classe
    Par chennuo dans le forum Langage
    R�ponses: 2
    Dernier message: 10/03/2006, 22h17
  3. [JUnit] [Test][D�butant] Constructeur priv�
    Par Shabata dans le forum Tests et Performance
    R�ponses: 2
    Dernier message: 12/01/2006, 15h45
  4. [D7] constructeur / destructeur
    Par raoulmania dans le forum Langage
    R�ponses: 2
    Dernier message: 16/12/2005, 18h00
  5. [D�butant]Constructeur et new/delete
    Par Geolem dans le forum C++
    R�ponses: 5
    Dernier message: 02/12/2005, 21h11

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