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 :

Itérateurs sur 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 Itérateurs sur pointeurs
    Bonjour,

    comme un schéma vaut mieux qu'un long discours, voici mon code:

    CODE QUI MARCHE:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for(unsigned int i(0); i < m_b->getComptes().size(); i++)
            m_ui->comboBox_choisirCompte->addItem(QString::fromStdString((m_b->getComptes().at(i))->getId()));
    CODE QUI NE MARCHE PAS:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
        std::vector<Compte*>::iterator it;
        for(it = m_b->getComptes().begin(); it != m_b->getComptes().end(); ++it)
            m_ui->comboBox_choisirCompte->addItem(QString::fromStdString((*it)->getId()));

    Du coup je fais exactement la même boucle sur mon vector de Compte*, mais avec un itérateur mon programme plante a l'exécution !!

    Je ne vois pas pourquoi ??

    Merci à tous !

  2. #2
    Membre expérimenté Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Par défaut
    Hello,

    Il manque un peu de code pour pouvoir t'aider efficacement. Peux tu ajouter la définition de la classe à laquelle appartient m_b?

    Mais juste une question au hasard, la fonction getComptes() renvoie-t-elle une référence vers un vector ou une copie?

  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
    m_b est un pointeur sur un objet Banque, dont la définition est la suivante:

    Banque.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
    class Banque
    {
        protected:
            std::vector<Compte*> m_comptes;
     
        public:
            Banque();
            Banque operator=(const Banque &banque);
            Banque(const Banque &banqueACopier);
            ~Banque();
     
            /* Accesseurs */
            std::vector<Compte*> getComptes() const;
            void setComptes(std::vector<Compte*> comptes);
    };
    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
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    #include "banque.h"
    using namespace std;
     
    /* Constructeur/Destructeur */
    Banque::Banque()
    {
        vector<Compte*> m_comptes;
    }
     
    Banque Banque::operator=(const Banque &banque)
    {
        m_comptes = banque.m_comptes;
     
        return *this;
    }
     
    Banque::Banque(const Banque &banqueACopier) : m_comptes(banqueACopier.m_comptes)
    {
    }
     
    Banque::~Banque()
    {
        vector<Compte*>::iterator it;
        for(it = m_comptes.begin(); it != m_comptes.end(); ++it)
            delete (*it);
     
        m_comptes.clear();
    }
     
    /* Accesseurs */
    vector<Compte*> Banque::getComptes() const { return m_comptes; }
    void Banque::setComptes(vector<Compte*> comptes) { m_comptes = comptes; }
    Pour ta question vikki, je ne sais pas s'il s'agit d'une référence ou d'une copie ?? Le code pourra surement te le dire... Et peut-être à ton tour tu pourras me l'indiquer ?? (inutile de signaler que je suis débutant en C++ )

    Merci !!

  4. #4
    Membre expérimenté Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Par défaut
    Telle que déclarée, getCompte renvoie une copie du vecteur m_comptes. Pour renvoyer une référence, change le prototype en:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    std::vector<Compte*> & getComptes() const;
    Le fait que tu renvoies une copie signifie que la condition d'arrêt de la boucle for s'effectue sur un iterateur 'end' pointant vers une copie temporaire de m_comptes (donc un vecteur différent de l'iterateur initiale 'begin', au passage pointant lui aussi vers une copie).

    J'ai du mal à dire si ces copies sont encore vivante à l'intérieur de la boucle, j'aurais tendance à dire oui. Si c'est le cas, la condition d'arrêt n'est jamais rencontrée, autrement le programme crash au premier dereferencement de l'iterateur. Dans tous les cas, renvoyer une référence devrait régler le problème.

    Je t'invite également à lire la faq sur les références.

  5. #5
    Membre expérimenté Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Par défaut
    Au passage, manipuler des pointeurs nus dans un conteneur est un peu dangereux, surtout lorsqu'ils sont copier via la fonction getComptes. En effet, qui est en charge de libérer la mémoire? Le destructeur de Banque dans ce cas, mais l'utilisateur de la classe ne devra surtout pas l'oublier. Et l'utilisation du constructeur par copie de Banque va automatiquement provoquer un crash à la destruction de l'objet (deux appels à delete sur un même pointeur;

    Exemple:


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    {
    std::vector<Compte*> comptes;
    for(int i=0; i< 10; i++)
      comptes.push_back(new Compte());
     
    Banque b1;
    b1.setComptes(comptes);
     
    Banque b2(b1);
     
    } //crash! b1 et b2 sont détruits, delete est appelé deux fois pour un meme pointeur
    L'utilisation de pointeurs intelligents pourraient fortement t'aider.

    Autre remarque, la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<Compte*> m_comptes;
    dans le constructeur n'est pas nécessaire (création d'un vecteur temporaire appelé m_comptes dans ton constructeur). Encore une fois, jette un coup d'œil à la faq, elle contient une mine d'informations claires pour t'aider à apprendre le C++ .

  6. #6
    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 pour tous ces conseils vikki, maintenant ça marche l'histoire du getComptes (enfin il faut enlever le const !!).

    Sinon la ligne vector<Compte*> m_comptes dans mon constructeur c'était pour initialiser mon attribut... ce serait peut-être mieux comme ça ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<Compte*> m_comptes = vector<Compte*>();
    Sinon merci pour l'histoire des pointeurs intelligents, j'ai bien compris la nuance. Ceci dit j'ai utilisé les pointeurs juste à titre pédagogique on va dire, pour apprendre à les manipuler ! Et puis je ne me suis pas posé la question car dans mon application je ne créé qu'un seul objet Banque au final Mais j'y repenserai dans un prochain programme...

  7. #7
    Membre expérimenté Avatar de vikki
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    292
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Mai 2007
    Messages : 292
    Par défaut
    vector<Compte*> m_comptes = vector<Compte*>();
    Cela revient au même qu'avant. Ne redéclare pas le type pour initialiser une variable membre dans le constructeur ou le compilateur va la considérer comme une nouvelle variable interne au constructeur. Tu initialise une variable soit via une liste d'initialisation, soit par affectation:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Banque::Banque()
      :m_comptes()         //liste d'initialisation, appel du constructeur par défaut de vector
    {
    }
     
    //ou alors
     
    Banque::Banque()
    {
        m_comptes = std::vector<Compte*>(); //initialisation par affectation
    }
    Mais dans ton, il n'est même pas nécessaire d'initialiser m_comptes: sont constructeur par défaut est automatiquement appelé dans le constructeur de Banque. La faq contient des infos intéressantes sur le fonctionnement de constructeurs, il ne faut pas hésiter à s'en servir .

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

Discussions similaires

  1. Réponses: 7
    Dernier message: 13/09/2009, 10h00
  2. [debutant] prob de comprehension sur pointeur **
    Par iznogoud36 dans le forum C
    Réponses: 10
    Dernier message: 14/09/2006, 13h13
  3. Besoin d'aide sur pointeur
    Par SebRs dans le forum C++
    Réponses: 2
    Dernier message: 18/05/2006, 10h21
  4. Iterateur sur pointeur de vector
    Par Pragmateek dans le forum SL & STL
    Réponses: 9
    Dernier message: 13/05/2006, 13h50
  5. pointeur sur pointeur
    Par gaut dans le forum C
    Réponses: 3
    Dernier message: 01/11/2005, 21h30

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