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++

  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 032
    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 032
    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 032
    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 032
    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.

  8. #8
    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
    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...
    Pas tel qu'il est présenté. J'ai plutôt l'impression que compte n'est pas vraiment une classe C++ mais plutôt une structure C.

  9. #9
    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
    Pas tel qu'il est présenté. J'ai plutôt l'impression que compte n'est pas vraiment une classe C++ mais plutôt une structure C.
    Que ce soit une structure ou une classe me semble un peu accessoire en l'occurence (surtout dans un programme clairement à but pédagogique). ce qui me semble plus important, c'est qu'un compte a un identifiant, probablement unique, et un solde, qu'il ne faut probablement pas dupliquer non plus.
    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.

  10. #10
    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
    A vrai dire je n'ai pas trop réfléchi pour utiliser vector<Compte> ou vector<Compte*> !

    J'ai utilisé des pointeurs sur Compte* pour utiliser les pointeurs... c'était plus pour m'entraîner et pour manipuler des pointeurs !!


    Si c'est pour le polymorphisme, alors il est justifié.
    NoIdea, peux-tu expliquer pourquoi tu dis ça ?? Je ne vois pas quelle est la différence entre l'utilisation de pointeurs ou non...

    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.
    ça veut dire quoi cette phrase ??

    Excusez-moi pour toutes ces questions mais... je débute en C++ Donc j'ai pas mal de questions !! En tout cas merci pour votre aide !!

  11. #11
    Membre Expert

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Par défaut
    Citation Envoyé par pacolito Voir le message
    A vrai dire je n'ai pas trop réfléchi pour utiliser vector<Compte> ou vector<Compte*> !

    J'ai utilisé des pointeurs sur Compte* pour utiliser les pointeurs... c'était plus pour m'entraîner et pour manipuler des pointeurs !!


    NoIdea, peux-tu expliquer pourquoi tu dis ça ?? Je ne vois pas quelle est la différence entre l'utilisation de pointeurs ou non...

    ça veut dire quoi cette phrase ??

    Excusez-moi pour toutes ces questions mais... je débute en C++ Donc j'ai pas mal de questions !! En tout cas merci pour votre aide !!
    Ces phrases un peu absconses signifient :

    1) pour la première, que lorsqu'on souhaite stocker dans un vecteur des objets dit polymorphiques (c'est à dire des instances de classes possédant des fonctions virtuelles) alors il est nécessaire de passer par un pointeur.

    2) pour la seconde, qu'il existe (au moins) deux types d'objets au niveau conceptuels : les objets qui permettent le stockage de valeurs (par exemple un objet chaine de caractère) : on préfère ne pas les manipuler sous la forme de pointeurs, de manière à pouvoir les copier aisément si nécessaire ; les objets à sémantique d'entité, qui représente une entité particulière dans un système (par exemple une chaise spécifique dans un salon), qui sont pas définition des choses qu'on ne copie pas (va copier la chaise en question ; tu obtiendra une autre chaise, mais ce n'est plus celle que tu as copié).

    Les histoires de sémantiques sont très liées au notions de conception - bien différencier la sémantique des objets qui composent une application permet de mieux définir leurs propriétés et la façon dont on va s'en servir, ce qui permet alors de proposer une conception plus proche des besoins exprimés pour cette application.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

+ 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