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 :

Un ou plusieurs pointeurs ?


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    55
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 55
    Par défaut Un ou plusieurs pointeurs ?
    Bonjour bonjour !!

    voici une petite question qui me tarraude ! Quelle est la meilleure solution parmi les 3 codes suivants pour supprimer mes objets :

    Solution 1:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Banque b;
    Compte* c;
     
    while(condition)
    {
        ... // récupération des paramètres nécessaires à la création d'un objet Compte
     
        c = new Compte(id, solde);
        b.addCompte(c);
    }
    delete c;

    Solution 2:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    Banque b;
    Compte* c;
     
    while(condition)
    {
        ... // récupération des paramètres nécessaires à la création d'un objet Compte
     
        c = new Compte(id, solde);
        b.addCompte(c);
        delete c;
    }

    Solution 3:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Banque b;
     
    while(condition)
    {
        ... // récupération des paramètres nécessaires à la création d'un objet Compte
     
        Compte* c = new Compte(id, solde);
        b.addCompte(c);
        delete c;
    }

    Je ne sais pas quelle solution est la mieux... d'ailleurs je ne suis pas sûr que la première soit correcte (on créé plusieurs pointeurs sur Compte et on ne fait qu'un seul delete !! C'est correct ça ??)

    Merci pour votre aide !!

  2. #2
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 033
    Billets dans le blog
    12
    Par défaut
    Je suis tenté de dire aucune des 3.
    Tout dépend de ce que fait ta fonction addCompte.
    Soit elle crée en interne un objet de type Compte pour elle même, à ce moment un passage par référence fait aussi bien l'affaire que le passage d'un pointeur et il devient inutile de créer dynamiquement ton Compte.
    Soit elle stocke le pointeur que tu lui donnes et tu ne dois alors surtout pas détruire le pointeur que tu lui as passé.

    Evidemment la première méthode est fausse, pour X new, il faut X delete. là tu as X new et 1 delete => memory leak.

    Voici 2 méthodes que je pourrais utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    while(condition)
    {
        ... // récupération des paramètres nécessaires à la création d'un objet Compte
        b.addCompte(id, solde); // on passe directement les arguments du constructeur du Compte qui est alors construit par banque
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    while(condition)
    {
        ... // récupération des paramètres nécessaires à la création d'un objet Compte
        b.addCompte( Compte( id, solde)); // on passe une référence sur un Compte construit statiquement à la volée.
    }
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    55
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 55
    Par défaut
    Merci dragonjoker59 pour ces précisions sur les pointeurs !! Du coup j'ai utilisé ta première solution, mais je n'ai pas le bon résultat et je ne sais vraiment pas pourquoi !! Pour mieux comprendre la suite, voici des indices
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Attribut de Banque : vector<Compte*> m_comptes;
    Attributs Compte : string id; double solde;
    Voici le code et le résultat :

    dans main.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    int main()
    {
        Banque b;
        b.loadBanque();
     
        for(unsigned int i(0); i < b.getComptes().size(); i++)
            cout << "Solde in main : " << (b.getComptes().at(i))->getSolde() << endl;
     
        return 0;
    }
    dans Banque.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
    void Banque::addCompte(string id, double solde)
    {
        Compte c(id, solde);
        m_comptes.push_back(&c);
    }
     
    void Banque::loadBanque()
    {
        string id;
        double solde;
     
        while(conditions)
        {
            /* récupération de id et solde */
            cout << "Solde in function load : " << solde << endl;
            addCompte(id, solde);
        }
     
        for(unsigned int i(0); i < m_comptes.size(); i++)
            cout << "Solde end load : " << (m_comptes.at(i))->getSolde() << endl;
    }
    Voici les résultats :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    Solde in function load : 1210 // ok
    Solde in function load : 2042.3 // ok
    Solde end load : 5.44973e+025 // où est passé 1210 ?
    Solde end load : 6.52786e-039 // où est passé 2042.3 ?
    Solde in main : 3.76419e-039 // ??
    Solde in main : 3.76419e-039 // ??
    Donc je ne comprends pas pourquoi mon vector ne se remplit pas correctement

    Merci pour l'aide...

  4. #4
    Expert confirmé

    Avatar de dragonjoker59
    Homme Profil pro
    Software Developer
    Inscrit en
    Juin 2005
    Messages
    2 033
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Software Developer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2005
    Messages : 2 033
    Billets dans le blog
    12
    Par défaut
    C'est ta fonction addCompte qui est fausse :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void Banque::addCompte(string id, double solde)
    {
        Compte c(id, solde);
        m_comptes.push_back(&c);
    }
    Là tu crées statiquement un Compte et tu passes son adresse à ton vecteur, hors ce compte est une variable temporaire, et dès que tu sors de la fonction, la valeur pointée par le pointeur ajouté au vecteur est indéfinie. Tu stockes des pointeurs dans ton vecteur, je te conseille donc de créer dynamiquement (avec un new) le compte :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    void Banque::addCompte(string id, double solde)
    {
        Compte * c = new Compte(id, solde);
        m_comptes.push_back(c);
    }
    Et dans ton destructeur de Banque, il ne faut pas oublier de détruire tes pointeurs de comptes :
    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
     
    Banque::~Banque()
    {
       for (size_t i = 0 ; i < m_comptes.size() ; i++)
       {
          delete m_comptes[i];
       }
       m_comptes.clear();
     
    //OU
     
       for (vector<Compte*>::iterator it = m_comptes.begin() ; it != m_comptes.end() ; ++it)
       {
          delete ( * it);
       }
       m_comptes.clear();
    }
    Si vous ne trouvez plus rien, cherchez autre chose...

    Vous trouverez ici des tutoriels OpenGL moderne.
    Mon moteur 3D: Castor 3D, presque utilisable (venez participer, il y a de la place)!
    Un projet qui ne sert à rien, mais qu'il est joli (des fois) : ProceduralGenerator (Génération procédurale d'images, et post-processing).

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    55
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations forums :
    Inscription : Octobre 2009
    Messages : 55
    Par défaut
    Edit : nous avons répondu au même moment Et puis tu as devancé mes questions... Donc j'ai toutes les réponses qu'il me fallait !!!

    Merci merci beaucoup, j'ai compris maintenant !!!!!!!!!! yes !!! Merci




    Je viens de modifier ma fonction addCompte et maintenant ça marche, mais...

    Ancienne fonction addCompte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    void Banque::addCompte(string id, float solde)
    {
        Compte c(id, solde);
        m_comptes.push_back(&c);
    }
    Nouvelle fonction addCompte:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Banque::addCompte(string id, float solde)
    {
        m_comptes.push_back( new Compte(id, solde) );
    }
    Du coup, comme je fais un "new" faut-il que je fasse un delete ?? Parce que là il y a une fuite mémoire non ??

    Et puis c'est quoi la différence entre les 2 méthodes ?? Pourquoi avec la première je n'ai pas les bons résultats, et avec la seconde j'ai les bons ?? Comprends pas...

    Merci !

  6. #6
    Membre éclairé

    Profil pro
    Inscrit en
    Avril 2010
    Messages
    356
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2010
    Messages : 356
    Par défaut
    Pourquoi des new partout ?
    Le vecteurs de Compte* c'est pour le polymorphisme ou pour une raison inconnue ?
    Si c'est pour le polymorphisme, alors il est justifié. Sinon, tu devrais voir si un std::vector<Compte> ne suffirait pas.

    Du coup, comme je fais un "new" faut-il que je fasse un delete ?? Parce que là il y a une fuite mémoire non ??
    Voir le code du destructeur de Banque poster par dragonjoker.

    Et puis c'est quoi la différence entre les 2 méthodes ?? Pourquoi avec la première je n'ai pas les bons résultats, et avec la seconde j'ai les bons ?? Comprends pas...
    Dans la première, voici ce que tu fais :

    Création d'un objet Compte à une adresse A.
    Stockage de l'adresse A dans le vector.
    Destruction de l'objet compte qui se trouve à l'adresse A.

    Question : il reste quoi à l'adresse A ?

    Dans le deuxième, voici ce que tu fais.

    Création d'un pointeur P.
    Affectation de P à l'adresse A qui contient un objet Compte.
    Passage de l'adresse A au vector.
    Destruction du pointeur P.

    Reste quoi à l'adresse A ?

  7. #7
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Yvelines (Île de France)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Par défaut
    Citation Envoyé par NoIdea Voir le message
    Pourquoi des new partout ?
    Le vecteurs de Compte* c'est pour le polymorphisme ou pour une raison inconnue ?
    Si c'est pour le polymorphisme, alors il est justifié. Sinon, tu devrais voir si un std::vector<Compte> ne suffirait pas.
    Une autre justification serait que Compte est une classe avec une sémantique d'entité, non de valeur, pour laquelle la copie n'aurait pas de sens, voire serait néfaste. Ce qui est probablement le cas avec un compte...

    Après, il y a sûrement moyen dans ce cas de travailler plus agréablement qu'avec un vector<Compte*>, par exemple avec un vector<shared_ptr<compte>>.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

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

Discussions similaires

  1. Problème de pointeur sur plusieurs threads
    Par Schpitt dans le forum Threads & Processus
    Réponses: 4
    Dernier message: 01/09/2010, 19h56
  2. passer plusieur pointeur dans un signal connect
    Par lrgtk dans le forum GTK+ avec C & C++
    Réponses: 12
    Dernier message: 19/01/2010, 15h14
  3. [.htaccess] Un domaine avec plusieurs pointeurs
    Par malipalo dans le forum Apache
    Réponses: 22
    Dernier message: 01/12/2009, 23h17
  4. Réponses: 9
    Dernier message: 11/11/2006, 13h10
  5. [Pointeur]plusieurs new, un seul delete ?
    Par snoop dans le forum C++
    Réponses: 4
    Dernier message: 18/07/2006, 18h33

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