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 :

Aide sur les pointeurs


Sujet :

C++

  1. #1
    Nouveau candidat au Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Novembre 2019
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Alimentation

    Informations forums :
    Inscription : Novembre 2019
    Messages : 2
    Par défaut Aide sur les pointeurs
    bonjour à tous,
    Je suis en train d'apprendre la programmation en C++ et j'ai u doute concernant la suppression propre des pointeurs afin d’éviter la surcharge mémoire
    voila une partie de mon programme concernant le main
    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
     
    #include <iostream>
    #include "Vehicule.h"
    #include "Moto.h"
    #include "Voiture.h"
    #include "Camion.h"
    #include "Garage.h"
     
    #include <string>
    #include<iostream>
    #include<vector>
    using namespace std;
     
    void presenter (Vehicule const &v) // prsente le vehicule passé en argument
    {
        v.affiche();
    }
     
    int main()
    {
        Garage garage;
        Vehicule* v =   new Voiture (25000, 1905, 18);
        garage.ajoutVehicule(v);
        garage.getListe() [0] ->affiche();
        cout <<"*************************************************" << endl;
        garage.supprimeVehicule();
     
        garage.~Garage(); // appel de la supression de tout les pointeurs
    et maintenant la classe Garage
    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
    #include "Garage.h"
    #include<vector>
    #include<string>
    #include<iostream>
     
    using namespace std;
     
    Garage::Garage()
    {
        //ctor
    }
     
    Garage::~Garage()
    {
        /*
        ******************************************************************************
           Ne jamais oublier d'effacer les pointeurs
             Risque de saturation mémoire
         *******************************************************************************
        */
     
        for(int i(0); i<m_listeVehicules.size(); ++i)
        {
            delete m_listeVehicules[i];  //On libère la i-ème case mémoire allouée
            m_listeVehicules[i] = 0;  //On met le pointeur à 0 pour éviter les soucis
        }
    }
    void Garage::ajoutVehicule(Vehicule* v)
    {
        m_listeVehicules.push_back(v);
    }
    void Garage::supprimeVehicule()
    {
        const int taille = m_listeVehicules.size() -1;
        cout << "taille avnat suppression : " << m_listeVehicules.size() << endl;
        delete m_listeVehicules[taille];
        m_listeVehicules[taille] = 0;
        m_listeVehicules.pop_back();
        cout << "taille apres suppression : " <<m_listeVehicules.size() << endl;
     
    //    m_listeVehicules.pop_back();
    }
    vector<Vehicule*> Garage::getListe() const
    {
        return m_listeVehicules;
    }
    Ma question est:

    Est-ce que ma façon de proceder à l'effacement est correct ?
    J'efface à la suppression d'un item dans la liste et la totalité dans ~garage()

    en vous remerciant d'avance pour vos réponses

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

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

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    C'est du vieux C++, ça.
    En C++ moderne, tu utilise un vector de std::unique_ptr<Voiture> à la place (et tu crées chaque voiture avec std::make_unique<>()) pour ne pas avoir à t'en soucier.
    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. #3
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 636
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 636
    Par défaut
    Salut, et bienvenue sur le forum.

    Avant toute chose :

    1- Pour tous les projets débutés après 1998, c'est une honte d'utiliser la directive using namespace std;. Comme on le répète à longueur d'année, et même plusieurs fois par semaine, je ne vais pas en donner la raison ici, mais je t'incite à lire cette intervention, qui ne date que d'il y a quelques jours, pour savoir pourquoi

    2- Si une fonction de ta classe permet d'accéder à une donnée membre de la classe (par exemple, ta fonction Garage::getListe()), il faut:
    1. renvoyer une référence constante sur la donnée renvoyée (à moins que ce soit un type primitif), pour éviter les copies inutiles
    2. déclarer ta fonction comme étant constante, pour que le compilateur sache que cette fonction n'a pas vocation à modifier l'instance de la classe


    Le prototype correct de cette fonction serait donc,
    Dans ton fichier d'en-tête
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    class Garage{
    public:
       std::vector<Vehicule *> const & getListe() const;
       /* je passe tout le reste */
    };
    dans ton fichier d'implémentation (garage.cpp)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    std::vector<Vehicule *> const & Garage::getListe() const{
        return m_listeVehicules;
    }
    3- Dans l'idéal, il faut respecter la loi dite de Déméter, qui nous dit:
    Citation Envoyé par la loi de Déméter
    Si un objet a (garage, dans la fonction principale) de type A (ta classe Garage manipule en interne un objet de b (m_listeVehicules) de type B (std::vector<Vehicule *>, dans la classe Garage), l'utilisateur de l'objet a (garage, dans la fonction principale) ne doit pas connaitre le type B (std::vector<Vehicule *>, dans la classe Garage) pour manipuler son A (ta classe Garage)
    (j'ai à chaque fois mis à quoi correspondaient a, A, b et B dans ton code entre parenthèses )

    Le but est que l'utilisation d'un std::vector<Vehicule*> reste tout à fait "transparent" pour l'utilisateur de ta classe, car ce n'est qu'un "détail d'implémentation". Dans l'idéal, tu devrais fournir "un certain nombre" de fonctions qui te permettront de respecter cette règle, par exemple:
    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 classe Garage telle que je la concois ;) */
    class Garage{
    public:
       /* parce qu'il n'est pas du ressort de l'utilisateur de créer le véhicule:
        * c'est du ressort du garage en lui-même
        */
        void ajouterVehicule(VehiculeType type, std::string const & marque, int kilometrage, int annee, int prix);
        size_t nombreVehicules() const; // pour savoir combien de véhicules il y a en stock
        /* on peut aller jusqu'à cacher à l'utilisateur le fait que Garage manipule des Vehicules */
        std::string const & marqueVehicule(size_t numero) const; // la marque
        int prixVehicule(size_t numero) const; // le prix
        int anneeVehicule(size_t numero) const; // l'annee
        int kilometrageVehicule(size_t numero) const; // le kilométrage
        /* si ton garage vend tous types de véhicules ;) */
        TypeVehicule typeVehicule(size_t numero) const; // voiture | camion | moto | char à voile ...
        void vendreVehicule(size_t numero); // la vente d'un véhicule le retire du stock
        /* le reste est du détail d'implémentation, j'en parle plus tard ;) */
    };
    De cette manière, il est particulièrement difficile pour l'utilisateur de l'utiilser de manière incorrecte: au pire, il se trompe dans le numéro associé au véhicule auquel il veut accéder et il est possible de vérifier celui-ci de manière systématique (pour qu'il n'essaye pas d'accéder au véhicule numéro 12 alors qu'il n'y en a que 10 en stock )

    Pour répondre à ta question:
    Depuis 2011 et l'arrivée de C++11 (cela fait quand même près de neuf ans maintenant !!! ) la bibliothèque standard propose plusieurs classes de pointeurs intelligents: des capsules RAII capable de déterminer quand il est temps de libérer la ressource auxquelles elles donnent accès; à savoir:
    1. la classe std::unique_ptr (qui est celle que je te recommande d'utiliser en priorité)
    2. le couple std::shared_ptr + std::weak_ptr (dont je ne te recommande l'usage que lorsque std::unique_ptr est inutilisable )

    Ces différentes classes (ainsi que les fonction std::make_unique et std::make_shared) te faciliteront grandement la vie en évitant tout problème

    Dans le cas présent, je te conseillerais donc d'utiliser un std::vector<std::unique_ptr<Vehicule>> pour garder les véhicules en stock de ton garage, et l'on peut donc compléter l'exemple de la classe Garage que je te présentais plus haut:
    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
    class Garage{
       /* parce que ce sera plus facile */
       using ptr_type = std::unique_ptr<Vehicule>;
    public:
       /* parce qu'il n'est pas du ressort de l'utilisateur de créer le véhicule:
        * c'est du ressort du garage en lui-même
        */
        void ajouterVehicule(VehiculeType type, std::string const & marque, int kilometrage, int annee, int prix);
        size_t nombreVehicules() const; // pour savoir combien de véhicules il y a en stock
        /* on peut aller jusqu'à cacher à l'utilisateur le fait que Garage manipule des Vehicules */
        std::string const & marqueVehicule(size_t numero) const; // la marque
        int prixVehicule(size_t numero) const; // le prix
        int anneeVehicule(size_t numero) const; // l'annee
        int kilometrageVehicule(size_t numero) const; // le kilométrage
        /* si ton garage vend tous types de véhicules ;) */
        TypeVehicule typeVehicule(size_t numero) const; // voiture | camion | moto | char à voile ...
        void vendreVehicule(size_t numero); // la vente d'un véhicule le retire du stock
        /* le reste est du détail d'implémentation, j'en parle plus tard ;) */
    private:
     
        std::vector<ptr_type> m_listeVehicules;
    };
    ET C'EST TOUT :
    • Pas besoin d'ajouter un constructeur
    • pas besoin de définir le destructeur
    • tout se fera automatiquement

    C'est beau quand le langage nous facilite la vie, non
    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

  4. #4
    Nouveau candidat au Club
    Homme Profil pro
    Lycéen
    Inscrit en
    Novembre 2019
    Messages
    2
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Lycéen
    Secteur : Alimentation

    Informations forums :
    Inscription : Novembre 2019
    Messages : 2
    Par défaut
    Merci pour ta réponse complète et explicative

    Je suis en train de suivre des tutos qui m'ont l'air de daté, vu les mises à jour

    J'ai encore pas mal de choses à apprendre

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

Discussions similaires

  1. aide sur les pointeurs
    Par kenshin64 dans le forum Débuter
    Réponses: 3
    Dernier message: 25/06/2012, 09h05
  2. Besoin d'un peu d'aide sur les pointeurs.
    Par techz dans le forum Débuter
    Réponses: 9
    Dernier message: 18/04/2009, 16h32
  3. Besoin d'aide sur les pointeurs
    Par amateurc dans le forum Ada
    Réponses: 5
    Dernier message: 03/06/2008, 14h58
  4. Aide sur les pointeurs + char
    Par Deejoh dans le forum Débuter
    Réponses: 13
    Dernier message: 18/09/2007, 12h55
  5. besoin d aide sur un exercice sur les pointeurs
    Par azumachakib69 dans le forum C
    Réponses: 3
    Dernier message: 28/12/2006, 01h16

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