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 :

Comportement d'un destructeur


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Avatar de guatto
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    179
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2014
    Messages : 179
    Par défaut Comportement d'un destructeur
    Bonjour tout le monde,

    Je suis encore débutant en C++, et j'aurais aimé apprendre plus sur le comportement du destructeur dans la libération de la mémoire, mais d'abord voici le code avec lequel je pratique :

    Fenetre.h:
    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
    33
    34
    35
    36
     
    #ifndef FENETRE_H
    #define FENETRE_H
     
    class Fenetre
    {
        public:
     
            Fenetre();
            Fenetre(int width, int height, int x, int y);
            /******************************************************/
            void launch();
            /******************************************************/
            virtual ~Fenetre();
     
        protected :
     
            void terminate();
     
        private:
     
            /******************************************************/
            SDL_Window* window;
            SDL_Renderer* renderer;
            SDL_Event event;
            bool isRunning;
     
            int F_Width;
            int F_Height;
            int F_PosX;
            int F_PosY;
            /******************************************************/
     
    };
     
    #endif // FENETRE_H
    Fenetre.cpp
    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
     
    #include <SDL2/SDL.h>
    #include "Fenetre.h"
    #include <iostream>
     
     
    Fenetre::Fenetre() : F_Width (640),F_Height(480),F_PosX(0),F_PosY(0),isRunning(false)
    {
     
       SDL_Init(SDL_INIT_EVERYTHING);
       window = SDL_CreateWindow("Test"
                                 ,SDL_WINDOWPOS_CENTERED
                                 ,SDL_WINDOWPOS_CENTERED
                                 ,F_Width
                                 ,F_Height
                                 ,0);
       renderer = SDL_CreateRenderer(window, -1, 0 );
     
    }
     
    Fenetre::Fenetre(int width = 640, int height = 480,int x = 200, int y = 100)
    {
     
        F_Width = width;
        F_Height = height;
        F_PosX = x;
        F_PosY = y;
        isRunning = false;
     
     
       SDL_Init(SDL_INIT_EVERYTHING);
       window = SDL_CreateWindow("Test"
                                 ,F_PosX
                                 ,F_PosY
                                 ,F_Width
                                 ,F_Height
                                 ,0);
       renderer = SDL_CreateRenderer(window, -1, 0 );
     
    }
     
    void Fenetre::launch()
    {
     
        isRunning = true;
        while(isRunning){
     
              while (SDL_PollEvent( &event )){
     
                if (event.type == SDL_QUIT){
     
                 isRunning = false;
     
                }
     
                  /**UPDATE THE CONTENT**/
                  std::cout << "Updated !" << std::endl;
     
              }
     
     
        }
     
        terminate();
     
    }
     
    void Fenetre::terminate()
    {
         std::cout << "Suppression du render et window" << std::endl;
         SDL_DestroyRenderer(renderer);
         SDL_DestroyWindow(window);
     
    }
     
    Fenetre::~Fenetre(){std::cout << "Suppression de l'objet" << std::endl;}
    et pour finir le Main.cpp :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    #include <SDL2/SDL.h>
    #include <iostream>
    #include "Fenetre.h"
     
    int main(int argc, char* argv[]){
     
        Fenetre * maFenetre = new Fenetre(800,600,10,10);
        maFenetre->launch();
        delete maFenetre;
     
      return 0;
    }
    Remarque : j'utilise Code::Blocks !

    Pour mes questions :
    -Est-ce que le destructeur fait son rôle ici, même s'il n'y a rien à l'intérieur ?
    -Est-ce que je suis une structure correcte dans mon code ?

    S'il y a d'autres remarques je serais heureux de les connaitre (bonnes ou mauvaises), Merci !

  2. #2
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Commençons par le début.
    Toute variable voit son contenu détruit lorsque le programme sort de sa portée de définition.

    Par exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main() {
        int a;
        {
            int b;
            {
                int c;
            } // destruction de c
        } // destruction de b
        return 0;  // destruction de a car sortie de la fonction.
    }
    Les types primitifs (int, long, float) sont simplement perdu de vue, la valeur reste "au fond" de la mémoire. C'est le choix le plus performant: il n'y a pas d'action du tout.
    Les énumérations se comportent comme des entiers (qu'elles sont en interne), et donc sont détruites de la même façon, par l'oubli.
    Les pointeurs et les références subissent le même sort: la variable elle-même est perdue.

    Les tableaux sont récursifs: leur destruction signifie la destruction de chaque élément (je ne sais plus si l'ordre est spécifié).
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    {
        int a[2] = {1, 2};
    }// destruction de tout a, ce qui signifie destruction de a[0] et a[1]
    Il reste donc deux sortes de variables: les unions et les classes.
    Les unions, je ne sais plus exactement, mais c'est si rare de parvenir à y mettre autre chose que des pointeurs, des entiers ou des flottants que la question ne se pose pas vraiment.

    Les valeurs dont le type est une classe sont détruites en appelant le destructeur de cette classe.

    Mais, ce procédé est indépendant de la gestion de la mémoire.

    Lorsqu'une variable locale est déclarée, de la mémoire lui est allouée automatiquement sur la pile (stack).
    Lorsqu'elle cesse d'être visible, sa valeur est détruite, et la mémoire correspondante est détruite.

    Lorsqu'au contraire, un bloc mémoire est utilisé pour créer une "variable", via new, on fait deux choses:
    demander une allocation dans le tas (heap), puis initialiser ce bloc mémoire en appelant dessus le constructeur avec les arguments donnés à new.

    Ce bloc mémoire n'est pas une variable. Il est accessible uniquement à partir de l'adresse retournée par new, qui faut donc impérativement stocker dans un pointeur.
    La destruction de ce bloc mémoire n'est pas faite automatiquement, puisqu'il n'y a pas de variable.
    C'est la charge de delete de d'abord détruire la valeur contenue (via le destructeur, si c'est une classe), puis de libérer le bloc mémoire.

    Note:
    Lorsqu'on réclame explicitement un bloc mémoire au système (via les fonctions C comme malloc), on obtient un bloc mémoire non typé, non initialisé.
    C'est la charge des "placement new" de finir le travail. Et de même, il faudrait détruire explicitement la valeur avant d'appeler free.
    D'une manière générale, n'utilise jamais ces fonctions C, plus fragiles que new et delete.


    Quoiqu'il en soit, n'utilise pas de pointeurs pour faire une allocation mémoire.
    Si jamais tu devais quand même le faire, utilise std::unique_ptr et std::make_uniqueSi vraiment cela ne convenait pas, alors il sera temps de réfléchir (à shared_ptr, probablement)

  3. #3
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Pour répondre plus précisément à tes questions.
    Oui, le destructeur est appelée par delete.
    Non, tu n'as aucun besoin d'avoir un pointeur
    Ca ne te choque pas de lancer une fenêtre?

    Une fenêtre, ca s'affiche.

    Première correction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     #include <SDL2/SDL.h>
    #include <iostream>
    #include "Fenetre.h"
     
    int main(int argc, char* argv[]){
        Fenetre maFenetre(800,600,10,10);
        maFenetre.launch();
        return 0;
    }
    Second correction:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     #include <SDL2/SDL.h>
    #include <iostream>
    #include "Fenetre.h"
     
    int main(int argc, char* argv[]){
        Application application;
     
        Fenetre maFenetre(800,600,10,10);
        application.setUI(maFenetre); //User Interface
     
        application.launch();
        return 0;
    }
    Et encore, la classe utilisée par application ne devrait pas être fenêtre, mais une classe GUI qui contiendrait la Fenetre, et qui hériterait de UI, la classe abstraite/l'interface définie pour montrer l'Application.

    Tu y gagnerais en séparation des responsabilités, ce qui est extrèmement important: Application gère le déroulement de l'application, UI celui de sa connexion à l'utilisateur.

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Février 2005
    Messages
    5 503
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Conseil

    Informations forums :
    Inscription : Février 2005
    Messages : 5 503
    Par défaut
    Commences déjà par te simplifier la vie, utilises une bibliothèque graphique C++ et pas C.
    Ton code est biscornu, non safe, peu maintenable, parce qu'une librairie C ne donne pas les outils simples pour le faire.
    Example:
    Pourquoi c'est ta fenêtre qui initialise la bibliothèque ? exemple, si t'as 2 fenêtres, c'est la merde.
    Utilisation de pointeur nu, c'est plus que dangereux, la moindre exception et c'est la cata.
    ...

    Les affichages dans la console, c'est tout juste bon pour du débogage dans les années 1970, utilisez un débogueur.

    Nom en Franglais, bof.

    Les noms mal choisis, car "launch" ne lance rien, elle boucle.

    Pourquoi utilisez-vous "new" et "delete" ? Vous n'avez pas besoin de cela pour utiliser correctement les destructeurs.

  5. #5
    Membre confirmé
    Avatar de guatto
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    179
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2014
    Messages : 179
    Par défaut
    Je vous remercie, il y a là des informations très utiles, je mets en résolu !

  6. #6
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Si tu connais déjà la SDL, la SFML ne devrait pas te poser trop de soucis, et elle est en C++, elle.
    Son utilisation est assez simple.

  7. #7
    Membre confirmé
    Avatar de guatto
    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2014
    Messages
    179
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2014
    Messages : 179
    Par défaut
    Non je débute encore, le choix de la SDL, c'était juste pour apprendre à maitriser le système d'objet en C++, comme j'avais l'habitude de faire en Java, mais je vais suivre ton conseil et apprendre celle-ci (SFML), merci encore !

  8. #8
    Expert éminent

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 202
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

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

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 202
    Par défaut
    Prend garde, la notion de classe du C++ est très différente de celle de Java.

    Si tu regardes dans nos discussions, tu verras nombre de références à SOLID et à RAII.
    A eux deux, ces sigles désignent la philosophie du C++.

    Le RAII consiste à utiliser la garantie que le destructeur de toute variable (correctement construite) sera appelée.
    On y gagne tellement de clareté qu'il est toujours dommage de ne pas s'en servir.

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

Discussions similaires

  1. open avec comport
    Par Goldocrack dans le forum C++Builder
    Réponses: 6
    Dernier message: 15/04/2009, 08h12
  2. [HttpClient] comportement bizarre, saute des catch()...
    Par iubito dans le forum Développement Web en Java
    Réponses: 4
    Dernier message: 04/02/2004, 15h25
  3. [Sybase] Comportement bizarre d'une table
    Par sdozias dans le forum Sybase
    Réponses: 4
    Dernier message: 03/02/2004, 10h39
  4. [Free Pascal] Comportement de Exec
    Par néo333 dans le forum Free Pascal
    Réponses: 3
    Dernier message: 01/11/2003, 17h46
  5. Réponses: 2
    Dernier message: 22/09/2003, 11h23

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