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 :

initialisation/suppression d'un vector dans une classe


Sujet :

C++

  1. #1
    Membre averti
    Femme Profil pro
    Ingénieur informatique scientifique
    Inscrit en
    Mai 2010
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur informatique scientifique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mai 2010
    Messages : 313
    Points : 301
    Points
    301
    Par défaut initialisation/suppression d'un vector dans une classe
    Bonjour,

    en codant mon premier programme C++ je me pose quelques questions par rapports aux tableaux dynamiques, notamment pour leur création et suppression.
    J'ai un attribut de classe de type vector<int> que je veux initialiser vide. Dans "MaClasse.h" j'ai écrit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<int> m_monAttribut;
    J'ai ensuite voulu gérer cet attribut dans le constructeur et destructeur de MaClasse mais je ne sais pas trop comment faire!
    J'ai l'impression que pour l'initialisation, il suffit de ne rien écrire à propos de cet attribut dans le constructeur car par défaut il est déjà initialisé vide. Est-ce correct?
    Deuxième question, comment faire pour libérer correctement la mémoire prise par ce tableau à la fin de mon programme?

    Merci d'avance pour votre aide!

  2. #2
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 196
    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 196
    Points : 17 165
    Points
    17 165
    Par défaut
    Bonjour,
    vector est une classe (en fait une template de classe), qui possède un constructeur et un destructeur.

    Le constructeur fais un new, tandis que le destructeur fais le delete.

    Avantage immédiat, le simple fait de déclarer le vector fais qu'il sera libéré (comme toute variable) lorsqu'il ne sera plus visible. Son destructeur étant appelé automatiquement à ce moment là, la mémoire est correctement libérée.


    Le principe de créer quelque chose de cher/rare dans le constructeur et de le libérer dans le destructeur s'appelle RAII, et c'est probablement la plus grande force du C++.
    Ca apporte une grande robustesse, tout en réduisant les détails techniques dans le code.

    D'autres classes suivent la même logique: les fstream ferment leur fichier, les unique_ptr libèrent leur pointeur, etc.

    C'est bien ce que tu essaie de faire.
    Et tu as bien raison, le constructeur par défaut est souvent suffisant (il défini un bloc mémoire pour 10 éléments), et le destructeur est correctement appelé à l'issu de l'appel de ton destructeur.

    Définir soit même le destructeur n'est en général nécessaire que pour les types très C, comme une socket ou un pointeur brut (ou nu).
    Cela dit, je te conseille de créer une capsule RAII dédiée pour chaque type C-esque à manier, plutot que les intégrer directement dans une classe de plus haut niveau.

  3. #3
    Membre averti
    Femme Profil pro
    Ingénieur informatique scientifique
    Inscrit en
    Mai 2010
    Messages
    313
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 34
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur informatique scientifique
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Mai 2010
    Messages : 313
    Points : 301
    Points
    301
    Par défaut
    Merci pour cette réponse très instructive complète!

    je te conseille de créer une capsule RAII dédiée pour chaque type C-esque à manier, plutot que les intégrer directement dans une classe de plus haut niveau.
    Pourrais-tu me donner un exemple concret car j'ai du mal à voir ce que tu veux dire?

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 196
    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 196
    Points : 17 165
    Points
    17 165
    Par défaut
    Suppose une (fausse) bibliothèque de sockets, nommée libskt, codée ainsi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    typedef struct skt_socket skt_t;
     
    skt_t* skt_open(const char*);
    void skt_close(skt_t*);
     
    void skt_send(skt_t*, const char* buf, unsigned int n);
    void skt_wait(skt_t*, char* buf, unsigned int n, unsigned int timer);
    Ca, c'est une socket fragile, parce que le code l'utilisant peut oublier de la fermer, ou le faire trop de fois (comme un free sur un malloc, ou un delete sur un new...)

    Une capsule ressemblerait au code 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
    //une struct vide, servant d'exception pour la socket
    struct failed_socket {};
     
    class raiied_skt {
    private:
        skt_t* socket;
    public:
        raiied_skt(const char* url) : socket (skt_open(url));{
            if(socket==NULL) throw failed_socket();
        }
        ~raiied_skt() {skt_close(socket);}
     
        raiied_skt& send(const char* buf, unsigned int n) {
            skt_send(socket, buf, n);
            return *this;
        }
     
        raiied_skt& send(std::vector<char> const& buf) {
            skt_send(socket, buf.data(), buf.size());
            return *this;
        }    
     
        raiied_skt& wait(char* buf, unsigned int n, unsigned int timer)  {
            skt_wait(socket, buf, n, timer);
            return *this;
        }
        raiied_skt& wait(std::vector<char>& buf, unsigned int n, unsigned int timer)  {
            skt_wait(socket, buf.data(), n, timer);
            return *this;
        }
    };
    Comme tu le vois, j'ai ajouté à l'interface de skt la possibilité d'accepter un vector de char.
    Ce n'est pas nécessaire, mais ca te montre qu'on peut un peu enrichir une capsule. (qui fait en même temps office de wrapper.

    Une autre approche, c'est d'avoir une capsule 'pseudo-pointeur'.
    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
    //une struct vide, servant d'exception pour la socket
    struct failed_socket {};
     
    class raiied_skt {
    private:
        skt_t* socket;
    public:
        raiied_skt(const char* url) : socket (skt_open(url));{
            if(socket==NULL) throw failed_socket();
        }
        ~raiied_skt() {skt_close(socket);}
     
         skt_t& operator*() {return *socket;}
         skt_t const& operator*() const {return *socket;}
     
         skt_t* operator->() {return socket;}
         skt_t const* operator->() const {return socket;}
    };
    Cela dit, je n'aime pas, parce que ca laisse la possibilité de tout casser ainsi:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    {
        raiied_skt skt("le beau serveur");
        skt_close(&*skt);
    }//ici, skt cesse d'être visible, elle est détruite.
    skt_close() est appelée une deuxième fois, lors de la destruction de skt.

Discussions similaires

  1. Vector dans une classe qui vient de Java
    Par JeanNoel53 dans le forum C++
    Réponses: 7
    Dernier message: 13/07/2010, 17h41
  2. Pb std::vector dans une classe
    Par didi_di dans le forum Langage
    Réponses: 8
    Dernier message: 17/11/2009, 11h07
  3. vector dans une class
    Par squale69 dans le forum C++
    Réponses: 7
    Dernier message: 11/04/2008, 21h05
  4. Récupérer un Vector d'une classe dans une autre
    Par javamax dans le forum Langage
    Réponses: 2
    Dernier message: 22/10/2006, 14h29
  5. Réponses: 10
    Dernier message: 24/09/2005, 20h19

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